Files
outline/server/queues/tasks/CleanupDocumentInsightsTask.test.ts
Tom Moor 4774fa4fd0 Weekly insights rollup (#12113)
* Weekly insights rollup

* fix: Avoid eager db instance creation in DocumentInsight model

Importing sequelize at the top level triggered createDatabaseInstance
during module load, which caused unrelated test suites that transitively
require the model to fail. Use the instance-bound this.sequelize in the
static method instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix: Skip soft-deleted documents in weekly insights rollup

The weekly task was deleting daily rows for soft-deleted documents
without creating a weekly replacement, since rollupPeriod filters them
out. Join to documents in both the week-discovery query and the DELETE
to keep behavior consistent — historical daily rows for deleted docs are
left for the cleanup task to remove at the retention boundary.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* refactor: Bind cutoff days param and add date predicate in weekly rollup

Moves CUTOFF_DAYS from string interpolation to a bound parameter and
adds a plain `date <` predicate so the planner can use the
(documentId, date, period) index before evaluating date_trunc.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-17 09:48:30 -04:00

43 lines
1.2 KiB
TypeScript

import { format, subDays } from "date-fns";
import { DocumentInsight } from "@server/models";
import { buildDocument, buildTeam } from "@server/test/factories";
import CleanupDocumentInsightsTask from "./CleanupDocumentInsightsTask";
const daysAgo = (n: number) => subDays(new Date(), n);
const dayStr = (d: Date) => format(d, "yyyy-MM-dd");
describe("CleanupDocumentInsightsTask", () => {
it("deletes rows older than the retention window", async () => {
const team = await buildTeam();
const document = await buildDocument({
teamId: team.id,
publishedAt: new Date(),
});
await DocumentInsight.create({
documentId: document.id,
teamId: team.id,
date: dayStr(daysAgo(400)),
viewCount: 1,
});
await DocumentInsight.create({
documentId: document.id,
teamId: team.id,
date: dayStr(daysAgo(5)),
viewCount: 1,
});
await new CleanupDocumentInsightsTask().perform();
const dates = (
await DocumentInsight.findAll({
where: { documentId: document.id },
order: [["date", "ASC"]],
})
).map((i) => i.date);
expect(dates).not.toContain(dayStr(daysAgo(400)));
expect(dates).toContain(dayStr(daysAgo(5)));
});
});