History

Initialize persistence service directly from Effect SQLite adapter

Cursor Agent committed 8 months ago

Commit aa2d6e71 parent 91128181 file · +37 −11Browse files

Unified · Split

apps/server/src/persistenceService.ts+37−11
@@ -66,7 +66,6 @@ import { · 65 unmodified lines
6666 threadsUpdateResultSchema,
6767 } from "@t3tools/contracts";
6868
69−import { StateDb } from "./stateDb";
7069 import {
7170 countMessagesForThread as countMessagesForThreadEffect,
7271 deleteDocumentByIdAndKind as deleteDocumentByIdAndKindEffect,
@@ -101,7 +100,8 @@ import { · 28 unmodified lines
101100 readMetadataValue as readMetadataValueEffect,
102101 writeMetadataValue as writeMetadataValueEffect,
103102 } from "./persistence/metadataRepo";
104−import type { EffectSqliteDatabaseAdapter } from "./sqliteAdapter";
103+import { openSqliteDatabase, type EffectSqliteDatabaseAdapter, type SqliteDatabase } from "./sqliteAdapter";
104+import { runStateMigrations } from "./stateMigrations";
105105
106106 const METADATA_KEY_PROJECTS_JSON_IMPORTED = "migration.projects_json_imported";
107107 const METADATA_KEY_APP_SETTINGS = "app.settings.v1";
@@ -466,22 +466,32 @@ function mergeTurnSummaryFiles( · 358 unmodified lines
466466 }
467467
468468 export class PersistenceService extends EventEmitter<PersistenceServiceEvents> {
469− private readonly stateDb: StateDb;
470− private readonly db: StateDb["db"];
469+ private readonly db: SqliteDatabase;
471470 private readonly sessionThreadIds = new Map<string, string>();
472471 private readonly runtimeThreadIds = new Map<string, string>();
473472
474473 constructor(options: PersistenceServiceOptions) {
475474 super();
476− this.stateDb = new StateDb({ dbPath: options.dbPath });
477− this.db = this.stateDb.db;
475+ const dbPath = path.resolve(options.dbPath);
476+ fs.mkdirSync(path.dirname(dbPath), { recursive: true });
477+ this.db = openSqliteDatabase(dbPath);
478+ try {
479+ runStateMigrations(this.db);
480+ } catch (error) {
481+ try {
482+ this.db.close();
483+ } catch {
484+ // Best effort close on failed initialization.
485+ }
486+ throw error;
487+ }
478488 if (options.legacyProjectsJsonPath) {
479489 this.importProjectsJsonIfNeeded(options.legacyProjectsJsonPath);
480490 }
481491 }
482492
483493 close(): void {
484− this.stateDb.close();
494+ this.db.close();
485495 }
486496
487497 getAppSettings(): AppSettings {
@@ -1379,7 +1389,7 @@ export class PersistenceService extends EventEmitter<PersistenceServiceEvents> { · 891 unmodified lines
13791389 }
13801390
13811391 let importedCount = 0;
1382− this.stateDb.transaction(() => {
1392+ this.runDbTransaction(() => {
13831393 try {
13841394 const raw = fs.readFileSync(normalizedPath, "utf8");
13851395 const payload = JSON.parse(raw) as { projects?: unknown };
@@ -1431,9 +1441,25 @@ export class PersistenceService extends EventEmitter<PersistenceServiceEvents> { · 45 unmodified lines
14311441 });
14321442 }
14331443
1444+ private runDbTransaction<T>(fn: () => T): T {
1445+ this.db.exec("BEGIN IMMEDIATE;");
1446+ try {
1447+ const result = fn();
1448+ this.db.exec("COMMIT;");
1449+ return result;
1450+ } catch (error) {
1451+ try {
1452+ this.db.exec("ROLLBACK;");
1453+ } catch {
1454+ // Preserve the original transactional failure.
1455+ }
1456+ throw error;
1457+ }
1458+ }
1459+
14341460 private withTransaction<T>(fn: (pendingEvents: StateEvent[]) => T): T {
14351461 const pendingEvents: StateEvent[] = [];
1436− const result = this.stateDb.transaction(() => fn(pendingEvents));
1462+ const result = this.runDbTransaction(() => fn(pendingEvents));
14371463 for (const event of pendingEvents) {
14381464 try {
14391465 this.emit("stateEvent", event);
@@ -1983,7 +2009,7 @@ export class PersistenceService extends EventEmitter<PersistenceServiceEvents> { · 543 unmodified lines
19832009 write();
19842010 return;
19852011 }
1986− this.stateDb.transaction(write);
2012+ this.runDbTransaction(write);
19872013 }
19882014
19892015 private runWithEffectSql<A>(
@@ -1997,6 +2023,6 @@ export class PersistenceService extends EventEmitter<PersistenceServiceEvents> { · 7 unmodified lines
19972023 }
19982024 }
19992025
2000−function isEffectSqliteDatabase(db: StateDb["db"]): db is EffectSqliteDatabaseAdapter {
2026+function isEffectSqliteDatabase(db: SqliteDatabase): db is EffectSqliteDatabaseAdapter {
20012027 return "runWithSqlClient" in db && typeof db.runWithSqlClient === "function";
20022028 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t