| @@ -77,23 +77,23 @@ import { · 76 unmodified lines |
| 77 | 77 | readNextSortKey as readNextSortKeyEffect, |
| 78 | 78 | upsertDocument as upsertDocumentEffect, |
| 79 | 79 | type DocumentRow, |
| 80 | | −} from "./persistence/documentsRepo"; |
| 80 | +} from "./persistence/repos/documentsRepo"; |
| 81 | 81 | import { |
| 82 | 82 | insertProviderEvent as insertProviderEventEffect, |
| 83 | 83 | listCompletedItemEventsBySessionTurn as listCompletedItemEventsBySessionTurnEffect, |
| 84 | 84 | listCompletedItemEventsByThreadTurn as listCompletedItemEventsByThreadTurnEffect, |
| 85 | 85 | listCompletedItemEventsByTurn as listCompletedItemEventsByTurnEffect, |
| 86 | 86 | type CompletedProviderItemRow, |
| 87 | | −} from "./persistence/providerEventsRepo"; |
| 87 | +} from "./persistence/repos/providerEventsRepo"; |
| 88 | 88 | import { |
| 89 | 89 | appendStateEvent as appendStateEventEffect, |
| 90 | 90 | listStateEventsAfterSeq as listStateEventsAfterSeqEffect, |
| 91 | 91 | readLastStateSeq as readLastStateSeqEffect, |
| 92 | | −} from "./persistence/stateEventsRepo"; |
| 92 | +} from "./persistence/repos/stateEventsRepo"; |
| 93 | 93 | import { |
| 94 | 94 | readMetadataValue as readMetadataValueEffect, |
| 95 | 95 | writeMetadataValue as writeMetadataValueEffect, |
| 96 | | −} from "./persistence/metadataRepo"; |
| 96 | +} from "./persistence/repos/metadataRepo"; |
| 97 | 97 | import { |
| 98 | 98 | buildUpdatedAppSettings, |
| 99 | 99 | resolveAppSettings, |
| @@ -119,8 +119,12 @@ import { · 19 unmodified lines |
| 119 | 119 | } from "./persistence/domain/stateSync"; |
| 120 | 120 | import { fallbackGroupId, normalizeTerminalIds, normalizeThread } from "./persistence/domain/threads"; |
| 121 | 121 | import { mergeTurnSummaryFiles, summarizeUnifiedDiff } from "./persistence/domain/turnSummaries"; |
| 122 | | −import { openSqliteDatabase, type EffectSqliteDatabaseAdapter, type SqliteDatabase } from "./sqliteAdapter"; |
| 123 | | −import { runStateMigrations } from "./stateMigrations"; |
| 122 | +import { resolvePersistenceConfig } from "./persistence/config"; |
| 123 | +import { PersistenceInitializationError } from "./persistence/errors"; |
| 124 | +import { runPersistenceMigrations } from "./persistence/migrator"; |
| 125 | +import { runWithSqlClient } from "./persistence/runtime"; |
| 126 | +import { openPersistenceSqliteDatabase } from "./persistence/sqliteLayer"; |
| 127 | +import type { SqliteDatabase } from "./sqliteAdapter"; |
| 124 | 128 | |
| 125 | 129 | const METADATA_KEY_PROJECTS_JSON_IMPORTED = "migration.projects_json_imported"; |
| 126 | 130 | const METADATA_KEY_APP_SETTINGS = "app.settings.v1"; |
| @@ -197,21 +201,22 @@ export class PersistenceService extends EventEmitter<PersistenceServiceEvents> { · 70 unmodified lines |
| 197 | 201 | |
| 198 | 202 | constructor(options: PersistenceServiceOptions) { |
| 199 | 203 | super(); |
| 200 | | − const dbPath = path.resolve(options.dbPath); |
| 201 | | − fs.mkdirSync(path.dirname(dbPath), { recursive: true }); |
| 202 | | − this.db = openSqliteDatabase(dbPath); |
| 204 | + const config = resolvePersistenceConfig(options); |
| 205 | + this.db = openPersistenceSqliteDatabase(config.dbPath); |
| 203 | 206 | try { |
| 204 | | − runStateMigrations(this.db); |
| 207 | + runPersistenceMigrations(this.db); |
| 205 | 208 | } catch (error) { |
| 206 | 209 | try { |
| 207 | 210 | this.db.close(); |
| 208 | 211 | } catch { |
| 209 | 212 | // Best effort close on failed initialization. |
| 210 | 213 | } |
| 211 | | − throw error; |
| 214 | + throw new PersistenceInitializationError("Failed to initialize persistence database", { |
| 215 | + cause: error, |
| 216 | + }); |
| 212 | 217 | } |
| 213 | | − if (options.legacyProjectsJsonPath) { |
| 214 | | − this.importProjectsJsonIfNeeded(options.legacyProjectsJsonPath); |
| 218 | + if (config.legacyProjectsJsonPath) { |
| 219 | + this.importProjectsJsonIfNeeded(config.legacyProjectsJsonPath); |
| 215 | 220 | } |
| 216 | 221 | } |
| 217 | 222 | |
| @@ -1716,13 +1721,6 @@ export class PersistenceService extends EventEmitter<PersistenceServiceEvents> { · 1498 unmodified lines |
| 1716 | 1721 | effect: Effect.Effect<A, unknown, SqlClient.SqlClient>, |
| 1717 | 1722 | fallback: () => A, |
| 1718 | 1723 | ): A { |
| 1719 | | − if (isEffectSqliteDatabase(this.db)) { |
| 1720 | | − return this.db.runWithSqlClient(effect); |
| 1721 | | − } |
| 1722 | | − return fallback(); |
| 1724 | + return runWithSqlClient(this.db, effect, fallback); |
| 1723 | 1725 | } |
| 1724 | 1726 | } |
| 1725 | | − |
| 1726 | | −function isEffectSqliteDatabase(db: SqliteDatabase): db is EffectSqliteDatabaseAdapter { |
| 1727 | | − return "runWithSqlClient" in db && typeof db.runWithSqlClient === "function"; |
| 1728 | | −} |