Skip to content

Commit 8762b65

Browse files
authored
Merge pull request #330 from weaviate/feat/list-backups
2 parents a225e29 + 8b2b490 commit 8762b65

File tree

4 files changed

+61
-91
lines changed

4 files changed

+61
-91
lines changed

src/backup/backupGetter.ts

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/backup/journey.test.ts

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -950,56 +950,6 @@ describe('fails restoring backup with invalid compression config', () => {
950950
it('cleans up', () => cleanupTestFood(client));
951951
});
952952

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

src/collections/backup/client.ts

Lines changed: 11 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,11 @@ 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+
* */
263+
list(backend: Backend): Promise<BackupReturn[]>;
254264
}

src/collections/backup/integration.test.ts

Lines changed: 50 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,36 @@ 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) => res.id)
135+
);
136+
}
137+
138+
const gotBackups: string[] = await client.backup
139+
.list('filesystem')
140+
.then((res) => res.map((bu) => bu.id));
141+
142+
// There may be other backups created in other tests;
143+
expect(gotBackups.length).toBeGreaterThanOrEqual(wantBackups.length);
144+
expect(gotBackups).toEqual(expect.arrayContaining(wantBackups));
145+
});
146+
});
147+
148+
function randomBackupId() {
149+
return 'backup-id-' + Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
150+
}
151+
});

0 commit comments

Comments
 (0)