perf(core): cache AgentStore SQLite connection per project
The dashboard re-instantiates AgentStore on every /api/agents request, and each instance was opening a fresh Database — re-running schema migrations and PRAGMA integrity_check on the full file. On a multi-hundred-MB DB that was 3-7s per request and leaked file handles. Sharing a cached Database keyed by rootDir reduces it to a one-time process cost. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
5
.changeset/agentstore-db-cache.md
Normal file
5
.changeset/agentstore-db-cache.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
Cache the AgentStore SQLite connection per project so the dashboard no longer reopens the database, re-runs migrations, and re-executes `PRAGMA integrity_check` on every `/api/agents` request. On large project databases this turned a sub-100ms call into multi-second latency that bled into every dashboard view fetching the agent list.
|
||||
@@ -187,6 +187,20 @@ function resolveCreationRuntimeConfig(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process-wide cache of initialized Database connections, keyed by absolute
|
||||
* rootDir. Without this, callers that re-instantiate AgentStore per request
|
||||
* (the dashboard does this in ~65 places) reopen the SQLite file, re-run the
|
||||
* full schema migration, and re-execute `PRAGMA integrity_check` (a full table
|
||||
* scan) every time — on a multi-hundred-MB DB that's seconds per request and
|
||||
* leaks file handles. Sharing one Database object reduces all of that to a
|
||||
* one-time cost per process.
|
||||
*
|
||||
* In-memory DBs are intentionally *not* cached: they're test-only and each
|
||||
* test wants its own isolated `:memory:` connection.
|
||||
*/
|
||||
const agentStoreDbCache = new Map<string, Database>();
|
||||
|
||||
/**
|
||||
* AgentStore manages agent lifecycle with SQLite-backed persistence.
|
||||
* Follows the same patterns as TaskStore for consistency.
|
||||
@@ -215,11 +229,25 @@ export class AgentStore extends EventEmitter {
|
||||
}
|
||||
|
||||
private get db(): Database {
|
||||
if (!this._db) {
|
||||
this._db = new Database(this.rootDir, { inMemory: this.inMemoryDb });
|
||||
if (this._db) return this._db;
|
||||
|
||||
if (this.inMemoryDb) {
|
||||
this._db = new Database(this.rootDir, { inMemory: true });
|
||||
this._db.init();
|
||||
return this._db;
|
||||
}
|
||||
return this._db;
|
||||
|
||||
const cached = agentStoreDbCache.get(this.rootDir);
|
||||
if (cached) {
|
||||
this._db = cached;
|
||||
return cached;
|
||||
}
|
||||
|
||||
const fresh = new Database(this.rootDir, { inMemory: false });
|
||||
fresh.init();
|
||||
agentStoreDbCache.set(this.rootDir, fresh);
|
||||
this._db = fresh;
|
||||
return fresh;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user