Add media storage limits, retention, and the near-limit flow
This commit is contained in:
@@ -10,6 +10,7 @@ import { join } from "node:path";
|
||||
import { ScrapeEngine, type FetchPage, type ScrapeBackend } from "../src/engine.js";
|
||||
import { extractMedia } from "../src/extract.js";
|
||||
import { PuppetBackend } from "../src/puppet-backend.js";
|
||||
import { isNearLimit, planRetention } from "../src/retention.js";
|
||||
import { dirSizeBytes, listScrapes, ScrapeStore } from "../src/store.js";
|
||||
import type { CoreAttachment, CoreMessage } from "../src/types.js";
|
||||
|
||||
@@ -173,7 +174,9 @@ void (async () => {
|
||||
const backend = new FakeBackend([
|
||||
{
|
||||
messages: [
|
||||
message("100", { attachments: [attachment({ filename: "one.png", contentType: "image/png" })] }),
|
||||
message("100", {
|
||||
attachments: [attachment({ filename: "one.png", contentType: "image/png", size: 10 })]
|
||||
}),
|
||||
message("101")
|
||||
]
|
||||
},
|
||||
@@ -202,6 +205,7 @@ void (async () => {
|
||||
assert.equal(stored.counts().image, 1);
|
||||
assert.equal(stored.queryMedia({ kind: "image" }).length, 1);
|
||||
assert.equal(stored.queryMedia({ kind: "video" }).length, 0);
|
||||
assert.equal(stored.sumBytesByKind().image, 10);
|
||||
stored.close();
|
||||
|
||||
assert.equal(listScrapes(root).length, 1);
|
||||
@@ -272,6 +276,42 @@ void (async () => {
|
||||
assert.deepEqual(calls[0], { channelId: "123", limit: 5, before: "60" });
|
||||
});
|
||||
|
||||
await test("retention marks the oldest completed scrapes up to the limit", () => {
|
||||
const scrapes = [
|
||||
{ id: "old", state: "done", createdAt: "2026-09-01T00:00:00.000Z", bytes: 600 },
|
||||
{ id: "new", state: "done", createdAt: "2026-09-02T00:00:00.000Z", bytes: 600 },
|
||||
{ id: "run", state: "running", createdAt: "2026-09-03T00:00:00.000Z", bytes: 600 }
|
||||
];
|
||||
|
||||
const plan = planRetention(scrapes, 1000, 100);
|
||||
assert.deepEqual(plan.mark, ["old", "new"]);
|
||||
assert.deepEqual(plan.delete, []);
|
||||
});
|
||||
|
||||
await test("retention deletes marked scrapes past the overrun allowance", () => {
|
||||
const scrapes = [
|
||||
{ id: "old", state: "pending-delete", createdAt: "2026-09-01T00:00:00.000Z", bytes: 600 },
|
||||
{ id: "new", state: "pending-delete", createdAt: "2026-09-02T00:00:00.000Z", bytes: 600 },
|
||||
{ id: "run", state: "running", createdAt: "2026-09-03T00:00:00.000Z", bytes: 600 }
|
||||
];
|
||||
|
||||
const plan = planRetention(scrapes, 1000, 5);
|
||||
assert.deepEqual(plan.delete, ["old", "new"]);
|
||||
assert.deepEqual(plan.mark, []);
|
||||
});
|
||||
|
||||
await test("retention leaves usage under the limit alone", () => {
|
||||
const plan = planRetention(
|
||||
[{ id: "one", state: "done", createdAt: "2026-09-01T00:00:00.000Z", bytes: 500 }],
|
||||
1000,
|
||||
5
|
||||
);
|
||||
|
||||
assert.deepEqual(plan, { mark: [], delete: [], totalBytes: 500 });
|
||||
assert.equal(isNearLimit(900, 1000, 90), true);
|
||||
assert.equal(isNearLimit(899, 1000, 90), false);
|
||||
});
|
||||
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
|
||||
if (failures > 0) {
|
||||
|
||||
Reference in New Issue
Block a user