Skip to content

Commit 8d3e8b1

Browse files
committed
Clean up empty child directories
1 parent 87c7fa9 commit 8d3e8b1

File tree

2 files changed

+60
-7
lines changed

2 files changed

+60
-7
lines changed

packages/mongodb-log-writer/src/mongo-log-manager.spec.ts

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('MongoLogManager', function () {
2828
});
2929

3030
afterEach(async function () {
31-
await fs.rmdir(directory, { recursive: true });
31+
await fs.rm(directory, { recursive: true });
3232
sinon.restore();
3333
});
3434

@@ -434,8 +434,8 @@ describe('MongoLogManager', function () {
434434
});
435435

436436
describe('with subdirectories', function () {
437-
it('cleans up in the expected order with maxLogFileCount', async function () {
438-
// This should exist since the file was created recently
437+
beforeEach(async function () {
438+
// Add a recent child file
439439
const childPath1 = path.join(
440440
directory,
441441
'subdir1',
@@ -445,7 +445,7 @@ describe('MongoLogManager', function () {
445445
await fs.writeFile(childPath1, '0'.repeat(1024));
446446
paths.push(childPath1);
447447

448-
// This should not exist since it was created a long time ago
448+
// Add an older child file
449449
const childPath2 = path.join(
450450
directory,
451451
'subdir2',
@@ -454,7 +454,9 @@ describe('MongoLogManager', function () {
454454
await fs.mkdir(path.join(directory, 'subdir2'), { recursive: true });
455455
await fs.writeFile(childPath2, '0'.repeat(1024));
456456
paths.push(childPath2);
457+
});
457458

459+
it('cleans up in the expected order with maxLogFileCount', async function () {
458460
const manager = new MongoLogManager({
459461
directory,
460462
retentionDays,
@@ -469,6 +471,41 @@ describe('MongoLogManager', function () {
469471

470472
expect(await getFilesState(paths)).to.equal('00110010');
471473
});
474+
475+
it('deletes empty directories after cleanup', async function () {
476+
// Add an old file in subdir1 - it should be deleted, but subdir1 should remain
477+
const oldSubdir1Child = path.join(
478+
directory,
479+
'subdir1',
480+
ObjectId.createFromTime(offset - 50).toHexString() + '_log',
481+
);
482+
await fs.writeFile(oldSubdir1Child, '0'.repeat(1024));
483+
paths.push(oldSubdir1Child);
484+
485+
const manager = new MongoLogManager({
486+
directory,
487+
retentionDays,
488+
maxLogFileCount: 3,
489+
onwarn,
490+
onerror,
491+
});
492+
493+
expect(await getFilesState(paths)).to.equal('111111111');
494+
495+
await manager.cleanupOldLogFiles({ recursive: true });
496+
497+
expect(await getFilesState(paths)).to.equal('001100100');
498+
499+
// subdir1 should have been left alone because of the newer child
500+
// subdir2 should have been deleted because it was empty
501+
await fs.stat(path.join(directory, 'subdir1'));
502+
try {
503+
await fs.stat(path.join(directory, 'subdir2'));
504+
expect.fail('subdir2 should have been deleted');
505+
} catch (err: any) {
506+
expect(err.code).to.equal('ENOENT');
507+
}
508+
});
472509
});
473510
});
474511

packages/mongodb-log-writer/src/mongo-log-manager.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,31 @@ export class MongoLogManager {
4747
this._options = options;
4848
}
4949

50-
private async deleteFile(path: string): Promise<void> {
50+
private async deleteFile(filePath: string): Promise<void> {
5151
try {
52-
await fs.unlink(path);
52+
await fs.unlink(filePath);
5353
// eslint-disable-next-line @typescript-eslint/no-explicit-any
5454
} catch (err: any) {
5555
if (err?.code !== 'ENOENT') {
56-
this._options.onerror(err as Error, path);
56+
this._options.onerror(err as Error, filePath);
5757
}
5858
}
59+
60+
let basePath = path.dirname(filePath);
61+
while (basePath !== this._options.directory) {
62+
// Delete empty directories up to the base directory
63+
try {
64+
await fs.rmdir(path.dirname(filePath));
65+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
66+
} catch (err: any) {
67+
// If the directory is not empty, we stop deleting.
68+
if (err?.code === 'ENOTEMPTY' || err?.code === 'ENOENT') {
69+
break;
70+
}
71+
}
72+
73+
basePath = path.dirname(basePath);
74+
}
5975
}
6076

6177
private get prefix() {

0 commit comments

Comments
 (0)