diff --git a/app/server/src/confluence/confluenceEngine.ts b/app/server/src/confluence/confluenceEngine.ts index 0bfe7c3..414be55 100644 --- a/app/server/src/confluence/confluenceEngine.ts +++ b/app/server/src/confluence/confluenceEngine.ts @@ -301,7 +301,12 @@ export async function runConfluenceReplay( const weeklyFull = await provider.resolveAsOf(symbol, '1wk', '9999-12-31'); const benchFull = await provider.resolveAsOf(BENCHMARK_SYMBOL, '1d', '9999-12-31'); + let asOfN = 0; for (const asOf of slice) { + asOfN += 1; + if (asOfN % 4 === 0) { + await new Promise((r) => setImmediate(r)); + } const dailyCut = daily.candles.filter((c) => (c.ts ?? '').slice(0, 10) <= asOf); const weeklyCut = weeklyFull.candles.filter((c) => (c.ts ?? '').slice(0, 10) <= asOf); const benchCut = benchFull.candles.filter((c) => (c.ts ?? '').slice(0, 10) <= asOf); @@ -391,6 +396,7 @@ export async function fillLearningLedger( complete: batch.complete, }; if (batch.evaluationsStored === 0) break; + await new Promise((r) => setImmediate(r)); } return { ...last, ledger: await learningLedgerStatus(db, cache) }; } diff --git a/app/server/src/index.ts b/app/server/src/index.ts index 0f004f8..977ce6f 100644 --- a/app/server/src/index.ts +++ b/app/server/src/index.ts @@ -264,7 +264,7 @@ async function confluenceTick(label: string): Promise { } = await import('./confluence/confluenceEngine.ts'); const { CONFLUENCE_LEARNING_UNIVERSE } = await import('./confluence/confluenceSeed.ts'); const replay = label === 'boot' - ? await fillLearningLedger(database, cache, 75_000) + ? await fillLearningLedger(database, cache, 12_000) : await runConfluenceReplay(database, cache, { symbols: CONFLUENCE_LEARNING_UNIVERSE, symbolsPerTick: LEARNING_REPLAY_SYMBOLS, @@ -331,7 +331,9 @@ const server = createServer(async (req, res) => { const url = new URL(req.url ?? '/', `http://localhost:${PORT}`); if (url.pathname === '/health') { res.writeHead(200, { 'content-type': 'application/json' }); - res.end(JSON.stringify({ ok: true, queue: queue.health() })); + // Cheap liveness only. queue.health() is a full SQLite scan and must not + // ride the docker healthcheck / login path. + res.end(JSON.stringify({ ok: true })); return; } if (url.pathname.startsWith('/api/trpc')) { diff --git a/app/src/lib/trpc.ts b/app/src/lib/trpc.ts index d95b876..bd79795 100644 --- a/app/src/lib/trpc.ts +++ b/app/src/lib/trpc.ts @@ -1008,7 +1008,8 @@ export const api = { }, auth: { signup: (email: string, password: string) => trpcMutate<{ userId: string }>("auth.signup", { email, password }), - login: (email: string, password: string, totp?: string) => trpcMutate<{ userId: string }>("auth.login", { email, password, ...(totp ? { totp } : {}) }), + login: (email: string, password: string, totp?: string) => + trpcMutate<{ userId: string }>("auth.login", { email, password, ...(totp ? { totp } : {}) }, 20_000), logout: () => trpcMutate<{ ok: boolean }>("auth.logout", {}), changePassword: (current: string, next: string) => trpcMutate<{ ok: boolean }>("auth.changePassword", { current, next }),