diff --git a/internal/cloud/access-control.ts b/internal/cloud/access-control.ts index f78d7636..44602d98 100644 --- a/internal/cloud/access-control.ts +++ b/internal/cloud/access-control.ts @@ -175,6 +175,11 @@ class AccessController { this.openFga = openFgaAuthorizer ?? createOpenFgaAuthorizer({ env, fetchImpl, now, configStore: store }); this.userBilling = userBillingClient ?? createUserBillingClient({ env, fetchImpl }); this.bootstrapAttempted = false; + if (typeof this.store?.ensureSchema === "function") { + this.store.ensureSchema().catch((error) => { + console.warn("access store schema warmup failed", error?.message ?? error); + }); + } } configureCodeAgentWorkspaceContext({ env = null, fetchImpl = null, traceStore = null, codeAgentChatResults = null } = {}) { @@ -1370,12 +1375,22 @@ class PostgresAccessStore extends MemoryAccessStore { super({ now }); this.query = query; this.schemaReady = false; + this.schemaReadyPromise = null; } async ensureSchema() { if (this.schemaReady) return; - for (const sql of ACCESS_SCHEMA_STATEMENTS) await this.query(sql, []); - this.schemaReady = true; + if (!this.schemaReadyPromise) { + this.schemaReadyPromise = (async () => { + for (const sql of ACCESS_SCHEMA_STATEMENTS) await this.query(sql, []); + this.schemaReady = true; + })(); + } + try { + await this.schemaReadyPromise; + } finally { + if (!this.schemaReady) this.schemaReadyPromise = null; + } } async countUsers() { await this.ensureSchema(); const result = await this.query("SELECT COUNT(*)::int AS count FROM users", []); return Number(result.rows?.[0]?.count ?? 0); }