Skip to content
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
1 change: 1 addition & 0 deletions CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
- Add: Pentaho CDA backward compatibility now supports browser-style `GET /plugin/cda/api/doQuery` with query params, including `outputType` (`json`, `csv`, `xls`) (#108)
- Fix: FDA deletion now ignores missing Minio objects so Sliding Window and fresh FDAs can be removed even when no files were uploaded (#169)
15 changes: 15 additions & 0 deletions src/lib/utils/aws.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ export async function dropFile(s3Client, bucket, path) {
}),
);
} catch (e) {
if (
e?.$metadata?.httpStatusCode === 404 ||
e?.name === 'NotFound' ||
e?.name === 'NoSuchKey' ||
e?.Code === 'NoSuchKey' ||
e?.code === 'NoSuchKey'
) {
return;
}

throw new FDAError(
500,
'S3ServerError',
Expand All @@ -97,6 +107,11 @@ export async function dropFile(s3Client, bucket, path) {

export async function dropFiles(s3Client, bucket, objsToRemove) {
logger.debug({ bucket, objsToRemove }, '[DEBUG]: dropFiles');

if (!objsToRemove?.length) {
return;
}

try {
await s3Client.send(
new DeleteObjectsCommand({
Expand Down
25 changes: 25 additions & 0 deletions test/unit/aws.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ describe('aws utils', () => {
});
});

test('dropFile ignores missing object errors', async () => {
const { dropFile } = await loadAwsModule();

currentS3Client.send.mockRejectedValueOnce(
Object.assign(new Error('missing'), {
name: 'NoSuchKey',
$metadata: { httpStatusCode: 404 },
}),
);

await expect(
dropFile(currentS3Client, 'bucket-a', 'file-a'),
).resolves.toBeUndefined();
});

test('dropFiles wraps delete errors with FDAError', async () => {
const { dropFiles } = await loadAwsModule();

Expand All @@ -144,6 +159,16 @@ describe('aws utils', () => {
});
});

test('dropFiles is a no-op for an empty object list', async () => {
const { dropFiles } = await loadAwsModule();

await expect(
dropFiles(currentS3Client, 'bucket-a', []),
).resolves.toBeUndefined();

expect(currentS3Client.send).not.toHaveBeenCalled();
});

test('moveObject wraps aws moving object errors with FDAError', async () => {
const { moveObject } = await loadAwsModule();

Expand Down
24 changes: 24 additions & 0 deletions test/unit/fda.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2152,6 +2152,30 @@ describe('deleteFDA', () => {
]);
});

test('deleteFDA removes FDA even when Minio has no matching objects', async () => {
mongoMocks.retrieveFDA.mockResolvedValue({
_id: 'mongo-id',
visibility: 'private',
servicePath: '/servicepath',
});
awsMocks.listObjects.mockResolvedValue([]);

await deleteFDA('svc', 'fdaA', 'private', '/servicepath');

expect(awsMocks.dropFiles).toHaveBeenCalledWith({}, 'svc', []);
expect(mongoMocks.removeFDA).toHaveBeenCalledWith(
'svc',
'fdaA',
'/servicepath',
);
expect(agenda.cancel).toHaveBeenCalledWith({
name: 'refresh-fda',
'data.service': 'svc',
'data.fdaId': 'fdaA',
'data.servicePath': '/servicepath',
});
});

test('throws FDANotFound when FDA does not exist', async () => {
mongoMocks.retrieveFDA.mockResolvedValue(undefined);
mongoMocks.retrieveFDAs.mockResolvedValue([]);
Expand Down
Loading