Skip to content

Commit 600be34

Browse files
committed
feat: add list backups to v3 API
1 parent a0fde37 commit 600be34

File tree

3 files changed

+66
-62
lines changed

3 files changed

+66
-62
lines changed

src/backup/journey.test.ts

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
import weaviate, { WeaviateClient } from '../v2/index.js';
88
import { Backend } from './index.js';
99

10-
import { requireAtLeast } from '../../test/version';
1110
const {
1211
createTestFoodSchemaAndData,
1312
cleanupTestFood,
@@ -951,62 +950,6 @@ describe('fails restoring backup with invalid compression config', () => {
951950
it('cleans up', () => cleanupTestFood(client));
952951
});
953952

954-
requireAtLeast(1, 32, 0).describe('get all exising backups', () => {
955-
const BACKEND: Backend = 'filesystem';
956-
const BACKUP_ID = randomBackupId();
957-
const BACKUP_ID_PIZZA = BACKUP_ID + '-pizza';
958-
const BACKUP_ID_SOUP = BACKUP_ID + '-soup';
959-
960-
const client = weaviate.client({
961-
scheme: 'http',
962-
host: 'localhost:8080',
963-
});
964-
965-
it('sets up', () => createTestFoodSchemaAndData(client));
966-
967-
it('creates backup pizza', () => {
968-
return client.backup
969-
.creator()
970-
.withIncludeClassNames(PIZZA_CLASS_NAME)
971-
.withBackend(BACKEND)
972-
.withBackupId(BACKUP_ID_PIZZA)
973-
.withWaitForCompletion(true)
974-
.do()
975-
.catch((err: any) => {
976-
throw new Error('should not fail on create backup: ' + err);
977-
});
978-
});
979-
980-
it('creates backup soup', () => {
981-
return client.backup
982-
.creator()
983-
.withIncludeClassNames(SOUP_CLASS_NAME)
984-
.withBackend(BACKEND)
985-
.withBackupId(BACKUP_ID_SOUP)
986-
.withWaitForCompletion(true)
987-
.do()
988-
.catch((err: any) => {
989-
throw new Error('should not fail on create backup: ' + err);
990-
});
991-
});
992-
993-
it('get all', () => {
994-
return client.backup
995-
.getter()
996-
.withBackend(BACKEND)
997-
.do()
998-
.then((allResponse) => {
999-
const relevant = allResponse.filter((b) => b.id === BACKUP_ID_SOUP || b.id === BACKUP_ID_PIZZA);
1000-
expect(relevant).toHaveLength(2);
1001-
})
1002-
.catch((err: any) => {
1003-
throw new Error('should not fail on getting all: ' + err);
1004-
});
1005-
});
1006-
1007-
it('cleans up', () => cleanupTestFood(client));
1008-
});
1009-
1010953
function assertThatAllPizzasExist(client: WeaviateClient) {
1011954
return assertThatAllFoodObjectsExist(client, 'Pizza', 4);
1012955
}

src/collections/backup/client.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
BackupStatusReturn,
3131
} from './types.js';
3232

33-
export const backup = (connection: Connection) => {
33+
export const backup = (connection: Connection): Backup => {
3434
const parseStatus = (res: BackupCreateStatusResponse | BackupRestoreResponse): BackupStatusReturn => {
3535
if (res.id === undefined) {
3636
throw new WeaviateUnexpectedResponseError('Backup ID is undefined in response');
@@ -202,6 +202,9 @@ export const backup = (connection: Connection) => {
202202
}
203203
: parseResponse(res);
204204
},
205+
list: (backend: Backend): Promise<BackupReturn[]> => {
206+
return connection.get<BackupReturn[]>(`/backups/${backend}`);
207+
},
205208
};
206209
};
207210

@@ -251,4 +254,14 @@ export interface Backup {
251254
* @throws {WeaviateBackupCanceled} If the backup restoration is canceled.
252255
*/
253256
restore(args: BackupArgs<BackupConfigRestore>): Promise<BackupReturn>;
257+
258+
/** List existing backups (completed and in-progress) created in a given backend.
259+
*
260+
* @param {Backend} backend Backend whence to list backups.
261+
* @returns {Promise<BackupReturn[]>} The response from Weaviate.
262+
* @throws {WeaviateInvalidInputError} If the input is invalid.
263+
* @throws {WeaviateBackupFailed} If the backup restoration fails.
264+
* @throws {WeaviateBackupCanceled} If the backup restoration is canceled.
265+
* */
266+
list(backend: Backend): Promise<BackupReturn[]>;
254267
}

src/collections/backup/integration.test.ts

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* eslint-disable @typescript-eslint/no-non-null-assertion */
22
/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
33
/* eslint-disable no-await-in-loop */
4+
import { requireAtLeast } from '../../../test/version.js';
45
import { Backend } from '../../backup/index.js';
56
import weaviate, { Collection, WeaviateClient } from '../../index.js';
67

@@ -88,6 +89,23 @@ describe('Integration testing of backups', () => {
8889
backend: res.backend as 'filesystem',
8990
});
9091
expect(status).not.toBe('SUCCESS'); // can be 'STARTED' or 'TRANSFERRING' depending on the speed of the test machine
92+
93+
// wait to complete so that other tests can run without colliding with Weaviate's lack of simultaneous backups
94+
let wait = true;
95+
while (wait) {
96+
const { status, error } = await collection.backup.getCreateStatus({
97+
backupId: res.id as string,
98+
backend: res.backend as Backend,
99+
});
100+
if (status === 'SUCCESS') {
101+
wait = false;
102+
}
103+
if (status === 'FAILED') {
104+
throw new Error(`Backup creation failed: ${error}`);
105+
}
106+
await new Promise((resolve) => setTimeout(resolve, 1000));
107+
}
108+
91109
return collection;
92110
};
93111

@@ -98,8 +116,38 @@ describe('Integration testing of backups', () => {
98116
.then(getCollection)
99117
.then(testCollectionWaitForCompletion)
100118
.then(testCollectionNoWaitForCompletion));
101-
});
102119

103-
function randomBackupId() {
104-
return 'backup-id-' + Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
105-
}
120+
requireAtLeast(1, 32, 0).it('get all exising backups', async () => {
121+
await clientPromise.then(async (client) => {
122+
await client.collections.create({ name: 'TestListBackups' }).then((col) => col.data.insert());
123+
124+
const wantBackups: string[] = [];
125+
for (let i = 0; i < 3; i++) {
126+
wantBackups.push(
127+
await client.backup
128+
.create({
129+
backupId: randomBackupId(),
130+
backend: 'filesystem',
131+
includeCollections: ['TestListBackups'],
132+
waitForCompletion: true,
133+
})
134+
.then((res) => {
135+
return res.id;
136+
})
137+
);
138+
}
139+
140+
const gotBackups: string[] = await client.backup
141+
.list('filesystem')
142+
.then((res) => res.map((bu) => bu.id));
143+
144+
// There may be other backups created in other tests;
145+
expect(gotBackups.length).toBeGreaterThanOrEqual(wantBackups.length);
146+
expect(gotBackups).toEqual(expect.arrayContaining(wantBackups));
147+
});
148+
});
149+
150+
function randomBackupId() {
151+
return 'backup-id-' + Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
152+
}
153+
});

0 commit comments

Comments
 (0)