mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Files] Adds bulk delete method (#155628)
## Summary Closes https://github.com/elastic/kibana/issues/154286 ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [x] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
3ce1ce389b
commit
c640c25c74
6 changed files with 57 additions and 3 deletions
|
@ -62,6 +62,16 @@ export interface DeleteFileArgs {
|
|||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments to delete files in a bulk request.
|
||||
*/
|
||||
export interface BulkDeleteFilesArgs {
|
||||
/**
|
||||
* File IDs.
|
||||
*/
|
||||
ids: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Arguments to get a file by ID.
|
||||
*/
|
||||
|
|
|
@ -12,6 +12,7 @@ import type {
|
|||
CreateFileArgs,
|
||||
UpdateFileArgs,
|
||||
DeleteFileArgs,
|
||||
BulkDeleteFilesArgs,
|
||||
GetByIdArgs,
|
||||
FindFileArgs,
|
||||
} from './file_action_types';
|
||||
|
@ -43,6 +44,13 @@ export interface FileServiceStart {
|
|||
*/
|
||||
delete(args: DeleteFileArgs): Promise<void>;
|
||||
|
||||
/**
|
||||
* Delete multiple files at once.
|
||||
*
|
||||
* @param args - delete files args
|
||||
*/
|
||||
bulkDelete(args: BulkDeleteFilesArgs): Promise<Array<PromiseSettledResult<void>>>;
|
||||
|
||||
/**
|
||||
* Get a file by ID. Will throw if file cannot be found.
|
||||
*
|
||||
|
|
|
@ -94,7 +94,10 @@ export class FileServiceFactoryImpl implements FileServiceFactory {
|
|||
await internalFileService.updateFile(args);
|
||||
},
|
||||
async delete(args) {
|
||||
return internalFileService.deleteFile(args);
|
||||
return await internalFileService.deleteFile(args);
|
||||
},
|
||||
async bulkDelete(args) {
|
||||
return await internalFileService.bulkDeleteFiles(args);
|
||||
},
|
||||
async getById<M>(args: GetByIdArgs) {
|
||||
return internalFileService.getById(args) as Promise<File<M>>;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import { Logger, SavedObjectsErrorHelpers } from '@kbn/core/server';
|
||||
import { AuditEvent, AuditLogger } from '@kbn/security-plugin/server';
|
||||
import pLimit from 'p-limit';
|
||||
|
||||
import { BlobStorageService } from '../blob_storage_service';
|
||||
import { InternalFileShareService } from '../file_share_service';
|
||||
|
@ -20,10 +21,14 @@ import type {
|
|||
CreateFileArgs,
|
||||
UpdateFileArgs,
|
||||
DeleteFileArgs,
|
||||
BulkDeleteFilesArgs,
|
||||
FindFileArgs,
|
||||
GetByIdArgs,
|
||||
} from './file_action_types';
|
||||
import { createFileClient, FileClientImpl } from '../file_client/file_client';
|
||||
|
||||
const bulkDeleteConcurrency = pLimit(10);
|
||||
|
||||
/**
|
||||
* Service containing methods for working with files.
|
||||
*
|
||||
|
@ -64,6 +69,14 @@ export class InternalFileService {
|
|||
await file.delete();
|
||||
}
|
||||
|
||||
public async bulkDeleteFiles({
|
||||
ids,
|
||||
}: BulkDeleteFilesArgs): Promise<Array<PromiseSettledResult<void>>> {
|
||||
const promises = ids.map((id) => bulkDeleteConcurrency(() => this.deleteFile({ id })));
|
||||
const result = await Promise.allSettled(promises);
|
||||
return result;
|
||||
}
|
||||
|
||||
private async get(id: string) {
|
||||
try {
|
||||
const { metadata } = await this.metadataClient.get({ id });
|
||||
|
|
|
@ -99,7 +99,7 @@ describe('FileService', () => {
|
|||
return file;
|
||||
}
|
||||
afterEach(async () => {
|
||||
await Promise.all(disposables.map((file) => file.delete()));
|
||||
await fileService.bulkDelete({ ids: disposables.map((d) => d.id) });
|
||||
const { files } = await fileService.find({ kind: [fileKind] });
|
||||
expect(files.length).toBe(0);
|
||||
disposables = [];
|
||||
|
@ -246,7 +246,7 @@ describe('FileService', () => {
|
|||
expect(result3.files.length).toBe(2);
|
||||
});
|
||||
|
||||
it('deletes files', async () => {
|
||||
it('deletes a single file', async () => {
|
||||
const file = await fileService.create({ fileKind, name: 'test' });
|
||||
const result = await fileService.find({ kind: [fileKind] });
|
||||
expect(result.files.length).toBe(1);
|
||||
|
@ -254,6 +254,25 @@ describe('FileService', () => {
|
|||
expect(await fileService.find({ kind: [fileKind] })).toEqual({ files: [], total: 0 });
|
||||
});
|
||||
|
||||
it('deletes a single file using the bulk method', async () => {
|
||||
const file = await fileService.create({ fileKind, name: 'test' });
|
||||
const result = await fileService.find({ kind: [fileKind] });
|
||||
expect(result.files.length).toBe(1);
|
||||
await fileService.bulkDelete({ ids: [file.id] });
|
||||
expect(await fileService.find({ kind: [fileKind] })).toEqual({ files: [], total: 0 });
|
||||
});
|
||||
|
||||
it('deletes multiple files using the bulk method', async () => {
|
||||
const promises = Array.from({ length: 15 }, (v, i) =>
|
||||
fileService.create({ fileKind, name: 'test ' + i })
|
||||
);
|
||||
const files = await Promise.all(promises);
|
||||
const result = await fileService.find({ kind: [fileKind] });
|
||||
expect(result.files.length).toBe(15);
|
||||
await fileService.bulkDelete({ ids: files.map((file) => file.id) });
|
||||
expect(await fileService.find({ kind: [fileKind] })).toEqual({ files: [], total: 0 });
|
||||
});
|
||||
|
||||
interface CustomMeta {
|
||||
some: string;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import { FileClient, FileServiceFactory, FileServiceStart, FilesSetup } from '.'
|
|||
export const createFileServiceMock = (): DeeplyMockedKeys<FileServiceStart> => ({
|
||||
create: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
bulkDelete: jest.fn(),
|
||||
deleteShareObject: jest.fn(),
|
||||
find: jest.fn(),
|
||||
getById: jest.fn(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue