mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
clawdbot-d02.1.9.1.27: normalize sqlite entry timestamps
This commit is contained in:
@@ -472,9 +472,9 @@ describe.each([fileBackedAdapter, sqliteAdapter])(
|
||||
const readScope = adapter.transcriptReadScope(paths);
|
||||
const event = {
|
||||
id: "event-1",
|
||||
message: { role: "user", content: "hello" },
|
||||
parentId: null,
|
||||
type: "message",
|
||||
payload: { content: "hello" },
|
||||
type: "metadata",
|
||||
};
|
||||
|
||||
await adapter.appendTranscriptEvent(scope, { type: "session", sessionId: "session-1" });
|
||||
@@ -491,9 +491,9 @@ describe.each([fileBackedAdapter, sqliteAdapter])(
|
||||
const readScope = sqliteAdapter.transcriptReadScope(paths);
|
||||
const event = {
|
||||
id: "event-1",
|
||||
message: { role: "user", content: "hello" },
|
||||
parentId: null,
|
||||
type: "message",
|
||||
payload: { content: "hello" },
|
||||
type: "metadata",
|
||||
};
|
||||
|
||||
await sqliteAdapter.appendTranscriptEvent(scope, event);
|
||||
@@ -869,4 +869,90 @@ describe("sqlite session normalization", () => {
|
||||
updated_at: expect.any(Number),
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes missing entry updatedAt before writing root and entry rows", async () => {
|
||||
const env = { ...process.env, OPENCLAW_STATE_DIR: paths.stateDir };
|
||||
await replaceSqliteSessionEntry(
|
||||
{
|
||||
agentId: "main",
|
||||
env,
|
||||
sessionKey: "agent:main:minimal",
|
||||
storePath: paths.sqlitePath,
|
||||
},
|
||||
{
|
||||
sessionId: "minimal-session",
|
||||
sessionStartedAt: 123,
|
||||
} as SessionEntry,
|
||||
);
|
||||
|
||||
const loaded = loadSqliteSessionEntry({
|
||||
agentId: "main",
|
||||
env,
|
||||
sessionKey: "agent:main:minimal",
|
||||
storePath: paths.sqlitePath,
|
||||
});
|
||||
expect(loaded).toMatchObject({
|
||||
sessionId: "minimal-session",
|
||||
sessionStartedAt: 123,
|
||||
updatedAt: 123,
|
||||
});
|
||||
|
||||
const database = openOpenClawAgentDatabase({
|
||||
agentId: "main",
|
||||
env,
|
||||
path: paths.sqlitePath,
|
||||
});
|
||||
const db = getNodeSqliteKysely<OpenClawAgentKyselyDatabase>(database.db);
|
||||
const row = executeSqliteQueryTakeFirstSync(
|
||||
database.db,
|
||||
db
|
||||
.selectFrom("sessions as s")
|
||||
.innerJoin("session_entries as se", "se.session_id", "s.session_id")
|
||||
.innerJoin("session_routes as sr", "sr.session_key", "se.session_key")
|
||||
.select([
|
||||
"s.created_at as root_created_at",
|
||||
"s.updated_at as root_updated_at",
|
||||
"se.entry_json",
|
||||
"se.updated_at as entry_updated_at",
|
||||
"sr.updated_at as route_updated_at",
|
||||
])
|
||||
.where("s.session_id", "=", "minimal-session"),
|
||||
);
|
||||
expect(row).toEqual({
|
||||
entry_json: JSON.stringify({
|
||||
sessionId: "minimal-session",
|
||||
sessionStartedAt: 123,
|
||||
updatedAt: 123,
|
||||
}),
|
||||
entry_updated_at: 123,
|
||||
root_created_at: 123,
|
||||
root_updated_at: 123,
|
||||
route_updated_at: 123,
|
||||
});
|
||||
|
||||
await upsertSqliteSessionEntry(
|
||||
{
|
||||
agentId: "main",
|
||||
env,
|
||||
sessionKey: "agent:main:minimal-upsert",
|
||||
storePath: paths.sqlitePath,
|
||||
},
|
||||
{
|
||||
sessionId: "minimal-upsert-session",
|
||||
},
|
||||
);
|
||||
const upsertRow = executeSqliteQueryTakeFirstSync(
|
||||
database.db,
|
||||
db
|
||||
.selectFrom("session_entries")
|
||||
.select(["entry_json", "updated_at"])
|
||||
.where("session_key", "=", "agent:main:minimal-upsert"),
|
||||
);
|
||||
const upsertEntry = JSON.parse(upsertRow?.entry_json ?? "{}") as Partial<SessionEntry>;
|
||||
expect(upsertEntry).toMatchObject({
|
||||
sessionId: "minimal-upsert-session",
|
||||
updatedAt: expect.any(Number),
|
||||
});
|
||||
expect(upsertRow?.updated_at).toBe(upsertEntry.updatedAt);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -779,8 +779,9 @@ function writeSessionEntry(
|
||||
entry: SessionEntry,
|
||||
): void {
|
||||
const db = getSessionKysely(database.db);
|
||||
const updatedAt = entry.updatedAt;
|
||||
const sessionRow = bindSqliteSessionRoot({ entry, sessionKey, updatedAt });
|
||||
const normalizedEntry = normalizeSqliteSessionEntryTimestamp(entry);
|
||||
const updatedAt = normalizedEntry.updatedAt;
|
||||
const sessionRow = bindSqliteSessionRoot({ entry: normalizedEntry, sessionKey, updatedAt });
|
||||
executeSqliteQuerySync(
|
||||
database.db,
|
||||
db
|
||||
@@ -817,20 +818,34 @@ function writeSessionEntry(
|
||||
.insertInto("session_entries")
|
||||
.values({
|
||||
session_key: sessionKey,
|
||||
session_id: entry.sessionId,
|
||||
entry_json: JSON.stringify(entry),
|
||||
session_id: normalizedEntry.sessionId,
|
||||
entry_json: JSON.stringify(normalizedEntry),
|
||||
updated_at: updatedAt,
|
||||
})
|
||||
.onConflict((conflict) =>
|
||||
conflict.column("session_key").doUpdateSet({
|
||||
session_id: entry.sessionId,
|
||||
entry_json: JSON.stringify(entry),
|
||||
session_id: normalizedEntry.sessionId,
|
||||
entry_json: JSON.stringify(normalizedEntry),
|
||||
updated_at: updatedAt,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeSqliteSessionEntryTimestamp(entry: SessionEntry): SessionEntry {
|
||||
if (typeof entry.updatedAt === "number" && Number.isFinite(entry.updatedAt)) {
|
||||
return entry;
|
||||
}
|
||||
const updatedAt =
|
||||
typeof entry.sessionStartedAt === "number" && Number.isFinite(entry.sessionStartedAt)
|
||||
? entry.sessionStartedAt
|
||||
: Date.now();
|
||||
return {
|
||||
...entry,
|
||||
updatedAt,
|
||||
};
|
||||
}
|
||||
|
||||
function ensureTranscriptSessionRoot(
|
||||
database: OpenClawAgentDatabase,
|
||||
scope: ResolvedTranscriptScope,
|
||||
|
||||
Reference in New Issue
Block a user