Skip to content

Commit 1d8dcf1

Browse files
authored
Add swap indexes feature for v0.30.0 (#1384)
Add swap indexes feature for v0.30.0 (#1384)
1 parent ea102e6 commit 1d8dcf1

File tree

4 files changed

+106
-1
lines changed

4 files changed

+106
-1
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,12 @@ client.index('myIndex').fetchInfo(): Promise<Index>
584584
client.index('myIndex').fetchPrimaryKey(): Promise<string | undefined>
585585
```
586586

587+
##### Swap two indexes
588+
589+
```ts
590+
client.swapIndexes(params: SwapIndexesParams): Promise<EnqueuedTask>
591+
```
592+
587593
### Settings <!-- omit in toc -->
588594

589595
#### [Get settings](https://docs.meilisearch.com/reference/api/settings.html#get-settings)

src/clients/client.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
KeysResults,
3030
TasksResults,
3131
EnqueuedTaskObject,
32+
SwapIndexesParams,
3233
CancelTasksQuery,
3334
DeleteTasksQuery,
3435
} from '../types'
@@ -186,6 +187,19 @@ class Client {
186187
}
187188
}
188189

190+
/**
191+
* Swaps a list of index tuples.
192+
*
193+
* @memberof MeiliSearch
194+
* @method swapIndexes
195+
* @param {SwapIndexesParams} params - List of indexes tuples to swap.
196+
* @returns {Promise<EnqueuedTask>} - Promise returning object of the enqueued task
197+
*/
198+
async swapIndexes(params: SwapIndexesParams): Promise<EnqueuedTask> {
199+
const url = '/swap-indexes'
200+
return await this.httpRequest.post(url, params)
201+
}
202+
189203
///
190204
/// TASKS
191205
///

src/types/types.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ export const enum TaskTypes {
231231
DOCUMENTS_ADDITION_OR_UPDATE = 'documentAdditionOrUpdate',
232232
DOCUMENT_DELETION = 'documentDeletion',
233233
SETTINGS_UPDATE = 'settingsUpdate',
234+
INDEXES_SWAP = 'indexSwap',
234235
TASK_DELETION = 'taskDeletion',
235236
SNAPSHOT_CREATION = 'snapshotCreation',
236237
TASK_CANCELATION = 'taskCancelation',
@@ -305,6 +306,9 @@ export type TaskObject = Omit<EnqueuedTaskObject, 'taskUid'> & {
305306
// Distinct attribute on settings actions
306307
distinctAttribute: DistinctAttribute
307308

309+
// Object containing the payload originating the `indexSwap` task creation
310+
swaps: SwapIndexesParams
311+
308312
// Number of tasks that matched the originalQuery filter
309313
matchedTasks?: number
310314

@@ -323,6 +327,10 @@ export type TaskObject = Omit<EnqueuedTaskObject, 'taskUid'> & {
323327
finishedAt: string
324328
}
325329

330+
export type SwapIndexesParams = Array<{
331+
indexes: string[]
332+
}>
333+
326334
type CursorResults<T> = {
327335
results: T[]
328336
limit: number
@@ -542,6 +550,9 @@ export const enum ErrorStatusCode {
542550
/** @see https://docs.meilisearch.com/errors/#dump_not_found */
543551
DUMP_NOT_FOUND = 'dump_not_found',
544552

553+
/** @see https://docs.meilisearch.com/errors/#duplicate_index_found */
554+
DUPLICATE_INDEX_FOUND = 'duplicate_index_found',
555+
545556
/** @see https://docs.meilisearch.com/errors/#missing_master_key */
546557
MISSING_MASTER_KEY = 'missing_master_key',
547558

tests/client.test.ts

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ErrorStatusCode, Health, Version, Stats } from '../src'
1+
import { ErrorStatusCode, Health, Version, Stats, TaskTypes } from '../src'
22
import { PACKAGE_VERSION } from '../src/package-version'
33
import {
44
clearAllIndexes,
@@ -18,6 +18,14 @@ const indexPk = {
1818
primaryKey: 'id',
1919
}
2020

21+
const index = {
22+
uid: 'movies_test',
23+
}
24+
25+
const index2 = {
26+
uid: 'movies_test2',
27+
}
28+
2129
afterAll(() => {
2230
return clearAllIndexes(config)
2331
})
@@ -365,6 +373,72 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])(
365373
ErrorStatusCode.INDEX_NOT_FOUND
366374
)
367375
})
376+
377+
test(`${permission} key: Swap two indexes`, async () => {
378+
const client = await getClient(permission)
379+
await client
380+
.index(index.uid)
381+
.addDocuments([{ id: 1, title: `index_1` }])
382+
const { taskUid } = await client
383+
.index(index2.uid)
384+
.addDocuments([{ id: 1, title: 'index_2' }])
385+
await client.waitForTask(taskUid)
386+
const swaps = [
387+
{
388+
indexes: [index.uid, index2.uid],
389+
},
390+
]
391+
392+
const swapTask = await client.swapIndexes(swaps)
393+
const resolvedTask = await client.waitForTask(swapTask.taskUid)
394+
const docIndex1 = await client.index(index.uid).getDocument(1)
395+
const docIndex2 = await client.index(index2.uid).getDocument(1)
396+
397+
expect(docIndex1.title).toEqual('index_2')
398+
expect(docIndex2.title).toEqual('index_1')
399+
expect(resolvedTask.type).toEqual(TaskTypes.INDEXES_SWAP)
400+
expect(resolvedTask.details.swaps).toEqual(swaps)
401+
})
402+
403+
test(`${permission} key: Swap two indexes with one that does not exist`, async () => {
404+
const client = await getClient(permission)
405+
406+
const { taskUid } = await client
407+
.index(index2.uid)
408+
.addDocuments([{ id: 1, title: 'index_2' }])
409+
410+
await client.waitForTask(taskUid)
411+
const swaps = [
412+
{
413+
indexes: ['does_not_exist', index2.uid],
414+
},
415+
]
416+
417+
const swapTask = await client.swapIndexes(swaps)
418+
const resolvedTask = await client.waitForTask(swapTask.taskUid)
419+
420+
expect(resolvedTask.type).toEqual(TaskTypes.INDEXES_SWAP)
421+
expect(resolvedTask.error?.code).toEqual(
422+
ErrorStatusCode.INDEX_NOT_FOUND
423+
)
424+
expect(resolvedTask.details.swaps).toEqual(swaps)
425+
})
426+
427+
// Should be fixed by rc1
428+
test(`${permission} key: Swap two one index with itself`, async () => {
429+
const client = await getClient(permission)
430+
431+
const swaps = [
432+
{
433+
indexes: [index.uid, index.uid],
434+
},
435+
]
436+
437+
await expect(client.swapIndexes(swaps)).rejects.toHaveProperty(
438+
'code',
439+
ErrorStatusCode.DUPLICATE_INDEX_FOUND
440+
)
441+
})
368442
})
369443

370444
describe('Test on base routes', () => {

0 commit comments

Comments
 (0)