mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-06 23:44:36 +00:00
feat(sqlite): cache insert statements for trigger performance
This commit is contained in:
parent
34bad4471a
commit
07e4a253ce
3 changed files with 65 additions and 25 deletions
|
|
@ -8,7 +8,7 @@ import type {
|
|||
MessageEntry,
|
||||
} from "@earendil-works/pi-agent-core";
|
||||
import { joinSqlFragments, type SqlQuery, sql } from "../sql.ts";
|
||||
import type { SqliteDatabase } from "../types.ts";
|
||||
import type { SqliteDatabase, SqliteStatement } from "../types.ts";
|
||||
|
||||
export interface EntryRow {
|
||||
id: string;
|
||||
|
|
@ -66,17 +66,35 @@ function parsePayload<TEntry extends Entry>(row: EntryRow): StoredEntryPayload<T
|
|||
return JSON.parse(row.payload) as StoredEntryPayload<TEntry>;
|
||||
}
|
||||
|
||||
const INSERT_ENTRY_SQL = `INSERT INTO entries (id, parent_id, seq, type, custom_type, timestamp, payload)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
function entryRowParams(entry: Entry): unknown[] {
|
||||
return [
|
||||
entry.id,
|
||||
entry.parentId,
|
||||
entry.seq,
|
||||
entry.type,
|
||||
entry.type === "custom" ? entry.customType : null,
|
||||
entry.timestamp,
|
||||
JSON.stringify(entryPayload(entry)),
|
||||
];
|
||||
}
|
||||
|
||||
export class EntryRowWriter {
|
||||
private readonly insertStatement: SqliteStatement;
|
||||
|
||||
constructor(db: SqliteDatabase) {
|
||||
this.insertStatement = db.prepare(INSERT_ENTRY_SQL);
|
||||
}
|
||||
|
||||
insert(entry: Entry): void {
|
||||
this.insertStatement.run(...entryRowParams(entry));
|
||||
}
|
||||
}
|
||||
|
||||
export function insertEntryRow(db: SqliteDatabase, entry: Entry): void {
|
||||
sql`INSERT INTO entries (id, parent_id, seq, type, custom_type, timestamp, payload)
|
||||
VALUES (
|
||||
${entry.id},
|
||||
${entry.parentId},
|
||||
${entry.seq},
|
||||
${entry.type},
|
||||
${entry.type === "custom" ? entry.customType : null},
|
||||
${entry.timestamp},
|
||||
${JSON.stringify(entryPayload(entry))}
|
||||
)`.run(db);
|
||||
db.prepare(INSERT_ENTRY_SQL).run(...entryRowParams(entry));
|
||||
}
|
||||
|
||||
export function decodeEntryRow(row: EntryRow): Entry {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { UsageRow, UsageScan } from "@earendil-works/pi-agent-core";
|
||||
import { joinSqlFragments, type SqlQuery, sql } from "../sql.ts";
|
||||
import type { SqliteDatabase } from "../types.ts";
|
||||
import type { SqliteDatabase, SqliteStatement } from "../types.ts";
|
||||
|
||||
export interface UsageLedgerRow {
|
||||
id: string;
|
||||
|
|
@ -11,16 +11,34 @@ export interface UsageLedgerRow {
|
|||
details: string | null;
|
||||
}
|
||||
|
||||
const INSERT_USAGE_LEDGER_SQL = `INSERT INTO usage_ledger (id, seq, entry_id, adjustment, usage, details)
|
||||
VALUES (?, ?, ?, ?, ?, ?)`;
|
||||
|
||||
function usageLedgerRowParams(row: UsageRow): unknown[] {
|
||||
return [
|
||||
row.id,
|
||||
row.seq,
|
||||
row.entryId ?? null,
|
||||
row.adjustment ? 1 : 0,
|
||||
JSON.stringify(row.usage),
|
||||
row.details === undefined ? null : JSON.stringify(row.details),
|
||||
];
|
||||
}
|
||||
|
||||
export class UsageLedgerRowWriter {
|
||||
private readonly insertStatement: SqliteStatement;
|
||||
|
||||
constructor(db: SqliteDatabase) {
|
||||
this.insertStatement = db.prepare(INSERT_USAGE_LEDGER_SQL);
|
||||
}
|
||||
|
||||
insert(row: UsageRow): void {
|
||||
this.insertStatement.run(...usageLedgerRowParams(row));
|
||||
}
|
||||
}
|
||||
|
||||
export function insertUsageLedgerRow(db: SqliteDatabase, row: UsageRow): void {
|
||||
sql`INSERT INTO usage_ledger (id, seq, entry_id, adjustment, usage, details)
|
||||
VALUES (
|
||||
${row.id},
|
||||
${row.seq},
|
||||
${row.entryId ?? null},
|
||||
${row.adjustment ? 1 : 0},
|
||||
${JSON.stringify(row.usage)},
|
||||
${row.details === undefined ? null : JSON.stringify(row.details)}
|
||||
)`.run(db);
|
||||
db.prepare(INSERT_USAGE_LEDGER_SQL).run(...usageLedgerRowParams(row));
|
||||
}
|
||||
|
||||
export function decodeUsageLedgerRow(row: UsageLedgerRow): UsageRow {
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ import type {
|
|||
} from "@earendil-works/pi-agent-core";
|
||||
import { prepareStorageCommit } from "@earendil-works/pi-agent-core";
|
||||
import { appendEntryToBranchIndex, scanBranchEntries, scanBranchEntryStructures } from "./session/branch-entries.ts";
|
||||
import { decodeEntryRow, insertEntryRow, readEntryRows, scanEntryRows } from "./session/entries.ts";
|
||||
import { decodeEntryRow, EntryRowWriter, readEntryRows, scanEntryRows } from "./session/entries.ts";
|
||||
import { deleteRegisterRow, listRegisterRows, readRegisterRow, setRegisterRow } from "./session/registers.ts";
|
||||
import { advanceNextSeq, readNextSeq } from "./session/session-sequences.ts";
|
||||
import { addUsageToSessionStats, incrementMessageCount, readSessionStats } from "./session/session-stats.ts";
|
||||
import { decodeUsageLedgerRow, insertUsageLedgerRow, scanUsageLedgerRows } from "./session/usage-ledger.ts";
|
||||
import { decodeUsageLedgerRow, scanUsageLedgerRows, UsageLedgerRowWriter } from "./session/usage-ledger.ts";
|
||||
import type { SqliteDatabase } from "./types.ts";
|
||||
|
||||
export interface SqliteStorageOptions {
|
||||
|
|
@ -28,6 +28,8 @@ export interface SqliteStorageOptions {
|
|||
export class SqliteStorage implements Storage {
|
||||
private readonly db: SqliteDatabase;
|
||||
private readonly now: () => number;
|
||||
private readonly entryWriter: EntryRowWriter;
|
||||
private readonly usageWriter: UsageLedgerRowWriter;
|
||||
private commitQueue: Promise<void> = Promise.resolve();
|
||||
private state: "open" | "closing" | "closed" = "open";
|
||||
private closePromise: Promise<void> | undefined;
|
||||
|
|
@ -35,6 +37,8 @@ export class SqliteStorage implements Storage {
|
|||
constructor(db: SqliteDatabase, options: SqliteStorageOptions = {}) {
|
||||
this.db = db;
|
||||
this.now = options.now ?? Date.now;
|
||||
this.entryWriter = new EntryRowWriter(db);
|
||||
this.usageWriter = new UsageLedgerRowWriter(db);
|
||||
}
|
||||
|
||||
commit(transaction: Transaction): Promise<CommitResult> {
|
||||
|
|
@ -107,14 +111,14 @@ export class SqliteStorage implements Storage {
|
|||
switch (write.kind) {
|
||||
case "entry": {
|
||||
const { kind: _kind, ...entry } = write;
|
||||
insertEntryRow(this.db, entry);
|
||||
this.entryWriter.insert(entry);
|
||||
appendEntryToBranchIndex(this.db, entry);
|
||||
if (entry.type === "message") incrementMessageCount(this.db);
|
||||
break;
|
||||
}
|
||||
case "usage": {
|
||||
const { kind: _kind, ...row } = write;
|
||||
insertUsageLedgerRow(this.db, row);
|
||||
this.usageWriter.insert(row);
|
||||
addUsageToSessionStats(this.db, row.usage);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue