refactor: normalize session route fields
Co-authored-by: adam91holt <adam91holt@users.noreply.github.com>
This commit is contained in:
@@ -157,6 +157,27 @@ describe("sessions", () => {
|
|||||||
expect(store["agent:main:two"]?.sessionId).toBe("sess-2");
|
expect(store["agent:main:two"]?.sessionId).toBe("sess-2");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("normalizes last route fields on write", async () => {
|
||||||
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-"));
|
||||||
|
const storePath = path.join(dir, "sessions.json");
|
||||||
|
await fs.writeFile(storePath, "{}", "utf-8");
|
||||||
|
|
||||||
|
await updateSessionStore(storePath, (store) => {
|
||||||
|
store["agent:main:main"] = {
|
||||||
|
sessionId: "sess-normalized",
|
||||||
|
updatedAt: 1,
|
||||||
|
lastChannel: " WhatsApp ",
|
||||||
|
lastTo: " +1555 ",
|
||||||
|
lastAccountId: " acct-1 ",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const store = loadSessionStore(storePath);
|
||||||
|
expect(store["agent:main:main"]?.lastChannel).toBe("whatsapp");
|
||||||
|
expect(store["agent:main:main"]?.lastTo).toBe("+1555");
|
||||||
|
expect(store["agent:main:main"]?.lastAccountId).toBe("acct-1");
|
||||||
|
});
|
||||||
|
|
||||||
it("updateSessionStore keeps deletions when concurrent writes happen", async () => {
|
it("updateSessionStore keeps deletions when concurrent writes happen", async () => {
|
||||||
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-"));
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-"));
|
||||||
const storePath = path.join(dir, "sessions.json");
|
const storePath = path.join(dir, "sessions.json");
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import path from "node:path";
|
|||||||
|
|
||||||
import JSON5 from "json5";
|
import JSON5 from "json5";
|
||||||
import { getFileMtimeMs, isCacheEnabled, resolveCacheTtlMs } from "../cache-utils.js";
|
import { getFileMtimeMs, isCacheEnabled, resolveCacheTtlMs } from "../cache-utils.js";
|
||||||
|
import { normalizeAccountId } from "../../utils/account-id.js";
|
||||||
|
import { normalizeMessageChannel } from "../../utils/message-channel.js";
|
||||||
import { mergeSessionEntry, type SessionEntry } from "./types.js";
|
import { mergeSessionEntry, type SessionEntry } from "./types.js";
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -41,6 +43,35 @@ function invalidateSessionStoreCache(storePath: string): void {
|
|||||||
SESSION_STORE_CACHE.delete(storePath);
|
SESSION_STORE_CACHE.delete(storePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSessionEntryDelivery(entry: SessionEntry): SessionEntry {
|
||||||
|
const normalizedLastChannel = normalizeMessageChannel(entry.lastChannel) ?? undefined;
|
||||||
|
const normalizedLastTo = typeof entry.lastTo === "string" ? entry.lastTo.trim() : undefined;
|
||||||
|
const normalizedLastAccountId = normalizeAccountId(entry.lastAccountId);
|
||||||
|
if (
|
||||||
|
normalizedLastChannel === entry.lastChannel &&
|
||||||
|
normalizedLastTo === entry.lastTo &&
|
||||||
|
normalizedLastAccountId === entry.lastAccountId
|
||||||
|
) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...entry,
|
||||||
|
lastChannel: normalizedLastChannel,
|
||||||
|
lastTo: normalizedLastTo || undefined,
|
||||||
|
lastAccountId: normalizedLastAccountId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeSessionStore(store: Record<string, SessionEntry>): void {
|
||||||
|
for (const [key, entry] of Object.entries(store)) {
|
||||||
|
if (!entry) continue;
|
||||||
|
const normalized = normalizeSessionEntryDelivery(entry);
|
||||||
|
if (normalized !== entry) {
|
||||||
|
store[key] = normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function clearSessionStoreCacheForTest(): void {
|
export function clearSessionStoreCacheForTest(): void {
|
||||||
SESSION_STORE_CACHE.clear();
|
SESSION_STORE_CACHE.clear();
|
||||||
}
|
}
|
||||||
@@ -114,6 +145,8 @@ async function saveSessionStoreUnlocked(
|
|||||||
// Invalidate cache on write to ensure consistency
|
// Invalidate cache on write to ensure consistency
|
||||||
invalidateSessionStoreCache(storePath);
|
invalidateSessionStoreCache(storePath);
|
||||||
|
|
||||||
|
normalizeSessionStore(store);
|
||||||
|
|
||||||
await fs.promises.mkdir(path.dirname(storePath), { recursive: true });
|
await fs.promises.mkdir(path.dirname(storePath), { recursive: true });
|
||||||
const json = JSON.stringify(store, null, 2);
|
const json = JSON.stringify(store, null, 2);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user