Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for pending update and error naming #311

Merged
merged 3 commits into from
Apr 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions src/meili-axios-error.ts → src/errors/meilisearch-error.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { AxiosError } from 'axios'
import * as Types from './types'
import * as Types from '../types'

const MeiliAxiosError: Types.MeiliAxiosErrorConstructor = class extends Error
implements Types.MeiliAxiosErrorInterface {
response?: Types.MeiliAxiosErrorResponse
request?: Types.MeiliAxiosErrorRequest
const MeiliSearchApiError: Types.MeiliSearchApiErrorConstructor = class
extends Error
implements Types.MeiliSearchApiErrorInterface {
response?: Types.MeiliSearchApiErrorResponse
request?: Types.MeiliSearchApiErrorRequest
type: string

constructor(error: AxiosError, cachedStack?: string) {
super(error.message)

this.name = 'MeiliSearch Error'
this.type = this.constructor.name
this.name = 'MeiliSearchApiError'

// Fetch the native error message but add our application name in front of it.
// This means slicing the "Error" string at the start of the message.
Expand Down Expand Up @@ -40,8 +42,11 @@ const MeiliAxiosError: Types.MeiliAxiosErrorConstructor = class extends Error
}
// use cached Stack on error object to keep the call stack
if (cachedStack && error.stack) {
this.stack = cachedStack
this.stack = `${this.name}: ${this.message}\n${cachedStack
.split('\n')
.slice(1)
.join('\n')}`
}
}
}
export default MeiliAxiosError
export default MeiliSearchApiError
11 changes: 11 additions & 0 deletions src/errors/meilisearch-timeout-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class MeiliSearchTimeOutError extends Error {
type: string
constructor(message: string) {
super(message)
this.name = 'MeiliSearchTimeOutError'
this.type = this.constructor.name
Error.captureStackTrace(this, MeiliSearchTimeOutError)
}
}

export { MeiliSearchTimeOutError }
26 changes: 23 additions & 3 deletions src/indexes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

'use strict'

import { MeiliSearchTimeOutError } from './errors/meilisearch-timeout-error'
import MeiliAxiosWrapper from './meili-axios-wrapper'
import * as Types from './types'
import { sleep } from './utils'

class Indexes extends MeiliAxiosWrapper implements Types.Indexes{
class Indexes extends MeiliAxiosWrapper implements Types.Indexes {
indexUid: string
constructor(config: Types.Config, indexUid: string) {
super(config)
Expand All @@ -32,6 +34,24 @@ class Indexes extends MeiliAxiosWrapper implements Types.Indexes{
return this.get(url)
}

async waitForPendingUpdate(
updateId: number,
{
timeOutMs = 5000,
intervalMs = 50,
}: { timeOutMs?: number; intervalMs?: number } = {}
) {
const startingTime = Date.now()
while (Date.now() - startingTime < timeOutMs) {
const response = await this.getUpdateStatus(updateId)
if (response.status !== 'enqueued') return response
await sleep(intervalMs)
}
throw new MeiliSearchTimeOutError(
`timeout of ${timeOutMs}ms has exceeded on process ${updateId} when waiting for pending update to resolve.`
)
}

/**
* Get the list of all updates
* @memberof Indexes
Expand Down Expand Up @@ -319,7 +339,7 @@ class Indexes extends MeiliAxiosWrapper implements Types.Indexes{
* @memberof Indexes
* @method updateSynonyms
*/
updateSynonyms(synonyms: object): Promise<object> {
updateSynonyms(synonyms: object): Promise<Types.EnqueuedUpdate> {
const url = `/indexes/${this.indexUid}/settings/synonyms`

return this.post(url, synonyms)
Expand All @@ -330,7 +350,7 @@ class Indexes extends MeiliAxiosWrapper implements Types.Indexes{
* @memberof Indexes
* @method resetSynonyms
*/
resetSynonyms(): Promise<object> {
resetSynonyms(): Promise<Types.EnqueuedUpdate> {
const url = `/indexes/${this.indexUid}/settings/synonyms`

return this.delete(url)
Expand Down
12 changes: 6 additions & 6 deletions src/meili-axios-wrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import instance, {
AxiosResponse,
CancelTokenSource,
} from 'axios'
import MeiliAxiosError from './meili-axios-error'
import MeiliSearchApiError from './errors/meilisearch-error'
import * as Types from './types'

class MeiliAxiosWrapper {
Expand Down Expand Up @@ -57,7 +57,7 @@ class MeiliAxiosWrapper {
.get(url, config)
.then((response: any) => response)
.catch((e) => {
const meiliError = new MeiliAxiosError(e, cachedStack)
const meiliError = new MeiliSearchApiError(e, cachedStack)
throw meiliError
})
}
Expand All @@ -73,7 +73,7 @@ class MeiliAxiosWrapper {
.post(url, data, config)
.then((response: any) => response)
.catch((e) => {
throw new MeiliAxiosError(e, cachedStack)
throw new MeiliSearchApiError(e, cachedStack)
})
}

Expand All @@ -88,7 +88,7 @@ class MeiliAxiosWrapper {
.put(url, data, config)
.then((response: any) => response)
.catch((e) => {
const meiliError = new MeiliAxiosError(e, cachedStack)
const meiliError = new MeiliSearchApiError(e, cachedStack)
throw meiliError
})
}
Expand All @@ -103,7 +103,7 @@ class MeiliAxiosWrapper {
.patch(url, data, config)
.then((response: any) => response)
.catch((e) => {
const meiliError = new MeiliAxiosError(e, cachedStack)
const meiliError = new MeiliSearchApiError(e, cachedStack)
throw meiliError
})
}
Expand All @@ -117,7 +117,7 @@ class MeiliAxiosWrapper {
.delete(url, config)
.then((response: any) => response)
.catch((e) => {
const meiliError = new MeiliAxiosError(e, cachedStack)
const meiliError = new MeiliSearchApiError(e, cachedStack)
throw meiliError
})
}
Expand Down
139 changes: 72 additions & 67 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { AxiosError, AxiosInstance, CancelTokenSource, AxiosRequestConfig, AxiosResponse } from 'axios'
import {
AxiosError,
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
CancelTokenSource,
} from 'axios'

///
/// Global interfaces
Expand Down Expand Up @@ -203,127 +209,126 @@ export interface SysInfoPretty {
** MeiliSearch Class
*/


export interface Indexes extends MeiliAxiosWrapper{
indexUid: string;
getUpdateStatus(updateId: number): Promise<Update>;
getAllUpdateStatus(): Promise<Update[]>;
search(query: string, options?: SearchParams): Promise<SearchResponse>;
show(): Promise<Index>;
updateIndex(data: UpdateIndexRequest): Promise<Index>;
deleteIndex(): Promise<string>;
getStats(): Promise<IndexStats>;
getDocuments(options?: GetDocumentsParams): Promise<Document[]>;
getDocument(documentId: string | number): Promise<Document>;
export interface Indexes extends MeiliAxiosWrapper {
indexUid: string
getUpdateStatus(updateId: number): Promise<Update>
getAllUpdateStatus(): Promise<Update[]>
search(query: string, options?: SearchParams): Promise<SearchResponse>
show(): Promise<Index>
updateIndex(data: UpdateIndexRequest): Promise<Index>
deleteIndex(): Promise<string>
getStats(): Promise<IndexStats>
getDocuments(options?: GetDocumentsParams): Promise<Document[]>
getDocument(documentId: string | number): Promise<Document>
addDocuments(
documents: Document[],
options?: AddDocumentParams
): Promise<EnqueuedUpdate>;
): Promise<EnqueuedUpdate>
updateDocuments(
documents: Document[],
options?: AddDocumentParams
): Promise<EnqueuedUpdate>;
deleteDocument(documentId: string | number): Promise<EnqueuedUpdate>;
deleteDocuments(documentsIds: string[] | number[]): Promise<EnqueuedUpdate>;
deleteAllDocuments(): Promise<EnqueuedUpdate>;
getSettings(): Promise<Settings>;
updateSettings(settings: Settings): Promise<EnqueuedUpdate>;
resetSettings(): Promise<EnqueuedUpdate>;
getSynonyms(): Promise<object>;
updateSynonyms(synonyms: object): Promise<object>;
resetSynonyms(): Promise<object>;
getStopWords(): Promise<string[]>;
updateStopWords(stopWords: string[]): Promise<EnqueuedUpdate>;
resetStopWords(): Promise<EnqueuedUpdate>;
getRankingRules(): Promise<string[]>;
updateRankingRules(rankingRules: string[]): Promise<EnqueuedUpdate>;
resetRankingRules(): Promise<EnqueuedUpdate>;
getDistinctAttribute(): Promise<string | void>;
updateDistinctAttribute(distinctAttribute: string): Promise<EnqueuedUpdate>;
resetDistinctAttribute(): Promise<EnqueuedUpdate>;
getSearchableAttributes(): Promise<string[]>;
): Promise<EnqueuedUpdate>
deleteDocument(documentId: string | number): Promise<EnqueuedUpdate>
deleteDocuments(documentsIds: string[] | number[]): Promise<EnqueuedUpdate>
deleteAllDocuments(): Promise<EnqueuedUpdate>
getSettings(): Promise<Settings>
updateSettings(settings: Settings): Promise<EnqueuedUpdate>
resetSettings(): Promise<EnqueuedUpdate>
getSynonyms(): Promise<object>
updateSynonyms(synonyms: object): Promise<object>
resetSynonyms(): Promise<object>
getStopWords(): Promise<string[]>
updateStopWords(stopWords: string[]): Promise<EnqueuedUpdate>
resetStopWords(): Promise<EnqueuedUpdate>
getRankingRules(): Promise<string[]>
updateRankingRules(rankingRules: string[]): Promise<EnqueuedUpdate>
resetRankingRules(): Promise<EnqueuedUpdate>
getDistinctAttribute(): Promise<string | void>
updateDistinctAttribute(distinctAttribute: string): Promise<EnqueuedUpdate>
resetDistinctAttribute(): Promise<EnqueuedUpdate>
getSearchableAttributes(): Promise<string[]>
updateSearchableAttributes(
searchableAttributes: string[]
): Promise<EnqueuedUpdate>;
resetSearchableAttributes(): Promise<EnqueuedUpdate>;
getDisplayedAttributes(): Promise<string[]>;
): Promise<EnqueuedUpdate>
resetSearchableAttributes(): Promise<EnqueuedUpdate>
getDisplayedAttributes(): Promise<string[]>
updateDisplayedAttributes(
displayedAttributes: string[]
): Promise<EnqueuedUpdate>;
resetDisplayedAttributes(): Promise<EnqueuedUpdate>;
getAcceptNewFields(): Promise<boolean>;
updateAcceptNewFields(acceptNewFields: boolean): Promise<EnqueuedUpdate>;
): Promise<EnqueuedUpdate>
resetDisplayedAttributes(): Promise<EnqueuedUpdate>
getAcceptNewFields(): Promise<boolean>
updateAcceptNewFields(acceptNewFields: boolean): Promise<EnqueuedUpdate>
}

export interface Meilisearch extends MeiliAxiosErrorInterface {
config: Config;
getIndex(indexUid: string): Indexes;
listIndexes(): Promise<IndexResponse[]>;
createIndex(data: IndexRequest): Promise<IndexResponse>;
getKeys(): Promise<Keys>;
isHealthy(): Promise<boolean>;
setHealthy(): Promise<void>;
setUnhealthy(): Promise<void>;
changeHealthTo(health: boolean): Promise<void>;
stats(): Promise<Stats>;
version(): Promise<Version>;
sysInfo(): Promise<SysInfo>;
prettySysInfo(): Promise<SysInfoPretty>;
export interface Meilisearch extends MeiliSearchApiErrorInterface {
config: Config
getIndex(indexUid: string): Indexes
listIndexes(): Promise<IndexResponse[]>
createIndex(data: IndexRequest): Promise<IndexResponse>
getKeys(): Promise<Keys>
isHealthy(): Promise<boolean>
setHealthy(): Promise<void>
setUnhealthy(): Promise<void>
changeHealthTo(health: boolean): Promise<void>
stats(): Promise<Stats>
version(): Promise<Version>
sysInfo(): Promise<SysInfo>
prettySysInfo(): Promise<SysInfoPretty>
}

export interface MeiliAxiosWrapper {
instance: AxiosInstance;
cancelTokenSource: CancelTokenSource;
instance: AxiosInstance
cancelTokenSource: CancelTokenSource
get<T = any, R = AxiosResponse<T>>(
url: string,
config?: AxiosRequestConfig
): Promise<R>;
): Promise<R>
post<T = any, R = AxiosResponse<T>>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<R>;
): Promise<R>
put<T = any, R = AxiosResponse<T>>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<R>;
): Promise<R>
patch<T = any, R = AxiosResponse<T>>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<R>;
): Promise<R>
delete<T = any, R = AxiosResponse<T>>(
url: string,
config?: AxiosRequestConfig
): Promise<R>;
): Promise<R>
}

/*
** ERROR HANDLER
*/

export interface MeiliAxiosErrorInterface extends Error {
export interface MeiliSearchApiErrorInterface extends Error {
name: string
message: string
stack?: string
}
export interface MeiliAxiosErrorResponse {
export interface MeiliSearchApiErrorResponse {
status?: number
statusText?: string
path?: string
method?: string
body?: object
}
export interface MeiliAxiosErrorRequest {
export interface MeiliSearchApiErrorRequest {
url?: string
path?: string
method?: string
}

export type MeiliAxiosErrorConstructor = new (
export type MeiliSearchApiErrorConstructor = new (
bidoubiwa marked this conversation as resolved.
Show resolved Hide resolved
error: AxiosError,
cachedStack?: string
) => void

export default Indexes;
export default Indexes
5 changes: 5 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function sleep(ms: number) {
bidoubiwa marked this conversation as resolved.
Show resolved Hide resolved
return new Promise((resolve) => setTimeout(resolve, ms))
}

export { sleep }
Loading