


























@@ -7,6 +7,7 @@ import { resolveMaintenanceConfigFromInput } from "./store-maintenance.js";
77import {
88capEntryCount,
99getActiveSessionMaintenanceWarning,
10+loadSessionStore,
1011pruneStaleEntries,
1112rotateSessionFile,
1213} from "./store.js";
@@ -135,21 +136,64 @@ describe("rotateSessionFile", () => {
135136storePath = path.join(testDir, "sessions.json");
136137});
137138138-it("file over maxBytes: renamed to .bak.{timestamp}, returns true", async () => {
139+it("file over maxBytes: copies to .bak.{timestamp}, returns true", async () => {
139140const bigContent = "x".repeat(200);
140141await fs.writeFile(storePath, bigContent, "utf-8");
141142142143const rotated = await rotateSessionFile(storePath, 100);
143144144145expect(rotated).toBe(true);
145-await expect(fs.stat(storePath)).rejects.toThrow();
146+await expect(fs.readFile(storePath, "utf-8")).resolves.toBe(bigContent);
146147const files = await fs.readdir(testDir);
147148const bakFiles = files.filter((f) => f.startsWith("sessions.json.bak."));
148149expect(bakFiles).toHaveLength(1);
149150const bakContent = await fs.readFile(path.join(testDir, bakFiles[0]), "utf-8");
150151expect(bakContent).toBe(bigContent);
151152});
152153154+it("keeps live sessions readable if rotation is interrupted before the final save", async () => {
155+const store = makeStore([["group:telegram:1", makeEntry(Date.now())]]);
156+await fs.writeFile(storePath, JSON.stringify(store, null, 2), "utf-8");
157+158+const rotated = await rotateSessionFile(storePath, 10);
159+const loaded = loadSessionStore(storePath, {
160+skipCache: true,
161+maintenanceConfig: {
162+mode: "enforce",
163+pruneAfterMs: DAY_MS,
164+maxEntries: 100,
165+rotateBytes: 1024 * 1024,
166+resetArchiveRetentionMs: null,
167+maxDiskBytes: null,
168+highWaterBytes: null,
169+},
170+});
171+172+expect(rotated).toBe(true);
173+expect(loaded["group:telegram:1"]?.sessionId).toBe(store["group:telegram:1"].sessionId);
174+});
175+176+it("keeps an empty live store authoritative when stale backups exist", async () => {
177+const staleStore = makeStore([["stale", makeEntry(Date.now())]]);
178+await fs.writeFile(`${storePath}.bak.${Date.now()}`, JSON.stringify(staleStore), "utf-8");
179+await fs.writeFile(storePath, "{}", "utf-8");
180+181+const loaded = loadSessionStore(storePath, {
182+skipCache: true,
183+maintenanceConfig: {
184+mode: "enforce",
185+pruneAfterMs: DAY_MS,
186+maxEntries: 100,
187+rotateBytes: 1024 * 1024,
188+resetArchiveRetentionMs: null,
189+maxDiskBytes: null,
190+highWaterBytes: null,
191+},
192+});
193+194+expect(loaded).toEqual({});
195+});
196+153197it("multiple rotations: only keeps 3 most recent .bak files", async () => {
154198let now = Date.now();
155199const nowSpy = vi.spyOn(Date, "now").mockImplementation(() => (now += 5));
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。