perf: overhaul session loading, caching, and runtime isolation (#2360)

Improve OpenChamber responsiveness under large session workloads while fixing
cache, synchronization, and persistence correctness across runtimes, projects,
directories, and worktrees.

- prioritize selected and visible sessions during bootstrap and defer
  non-critical enrichment work
- reduce redundant message loading, event processing, store publication, and
  hidden sidebar work
- prevent stale session and message requests from overwriting newer
  authoritative state
- preserve existing data when authoritative fetches fail instead of treating
  failures as successful empty responses
- scope session materialization, messages, drafts, queues, todos, pins,
  permissions, folders, tabs, Git state, and pull request data by runtime and
  directory identity
- harden runtime switching, reconnect, cleanup, mutation reconciliation, and
  persisted-state ordering
- preserve live subagent Task linkage when metadata arrives after an older
  message request or while streaming parts are suspended
- coalesce overlapping tail refreshes without losing newer refresh demand
- improve cold-session loading by moving deferrable work out of the critical
  bootstrap path
- isolate URL authentication, mobile credentials, native secrets, and other
  runtime-owned state across endpoint changes
- bound long-lived caches and remove avoidable allocations from event and
  rendering hot paths
- limit virtualization to archive collections where it improves rendering
  without disrupting active sidebar layout
- stabilize session folders, pin ordering, expanded state, and persisted
  sidebar behavior
- open skill files through the same secure editor and outside-workspace grant
  flow used by file navigation, including worktree sessions
- expand regression coverage for stale completions, runtime collisions,
  reconnect behavior, persistence races, authoritative empty results, and
  subagent refresh ordering
- document the updated synchronization, cache ownership, performance, and
  runtime-isolation invariants
This commit is contained in:
Bohdan Triapitsyn
2026-07-21 20:52:20 +03:00
committed by GitHub
parent 485efc7117
commit 85400459e9
197 changed files with 10835 additions and 3400 deletions
@@ -0,0 +1,18 @@
import { expect, mock, test } from "bun:test"
let runtimeKey = "runtime-a"
mock.module("@/lib/runtime-switch", () => ({ getRuntimeKey: () => runtimeKey }))
const { assertProviderCircuitClosed, recordProviderError, recordProviderSuccess } = await import("./provider-tracker")
test("isolates provider circuit state by runtime", () => {
for (let attempt = 0; attempt < 3; attempt += 1) recordProviderError("provider", 503)
expect(() => assertProviderCircuitClosed("provider")).toThrow()
runtimeKey = "runtime-b"
assertProviderCircuitClosed("provider")
runtimeKey = "runtime-a"
recordProviderSuccess("provider")
assertProviderCircuitClosed("provider")
})
@@ -8,6 +8,8 @@
* Inspired by HiveMind (arXiv:2604.17111) OS-inspired scheduling primitives.
*/
import { getRuntimeKey } from '@/lib/runtime-switch'
const DEFAULT_CIRCUIT_BREAK_THRESHOLD = 3
const DEFAULT_CIRCUIT_COOLDOWN_MS = 30_000
const DEFAULT_RETRY_BASE_DELAY_MS = 1000
@@ -15,6 +17,7 @@ const DEFAULT_RETRY_MAX_DELAY_MS = 32_000
const DEFAULT_RETRY_MAX_ATTEMPTS = 3
const PROVIDER_EVICTION_TTL_MS = 60 * 60 * 1000
const PROVIDER_EVICTION_INTERVAL_MS = 10 * 60 * 1000
const PROVIDER_MAX_ENTRIES = 200
const RETRYABLE_STATUS_CODES = new Set([429, 502, 503, 504])
@@ -27,15 +30,14 @@ type ProviderState = {
}
const providers = new Map<string, ProviderState>()
const providerKey = (providerID: string): string => JSON.stringify([getRuntimeKey(), providerID])
function evictStaleProviders(): void {
const now = Date.now()
for (const [providerID, state] of providers) {
if (
state.consecutiveErrors === 0 &&
now - state.lastErrorAt > PROVIDER_EVICTION_TTL_MS
) {
providers.delete(providerID)
for (const [key, state] of providers) {
const lastActivityAt = Math.max(state.lastErrorAt, state.circuitOpenAt)
if (now - lastActivityAt > PROVIDER_EVICTION_TTL_MS) {
providers.delete(key)
}
}
}
@@ -46,7 +48,8 @@ if (typeof setInterval !== 'undefined') {
}
function getOrCreateProvider(providerID: string): ProviderState {
let state = providers.get(providerID)
const key = providerKey(providerID)
let state = providers.get(key)
if (!state) {
state = {
consecutiveErrors: 0,
@@ -55,17 +58,19 @@ function getOrCreateProvider(providerID: string): ProviderState {
circuitOpenAt: 0,
circuitCooldownMs: DEFAULT_CIRCUIT_COOLDOWN_MS,
}
providers.set(providerID, state)
providers.set(key, state)
while (providers.size > PROVIDER_MAX_ENTRIES) {
const oldest = providers.keys().next().value
if (!oldest) break
providers.delete(oldest)
}
}
return state
}
export function recordProviderSuccess(providerID: string): void {
if (!providerID) return
const state = providers.get(providerID)
if (!state) return
state.consecutiveErrors = 0
state.lastErrorAt = 0
providers.delete(providerKey(providerID))
}
export function recordProviderError(providerID: string, status?: number): void {
@@ -91,7 +96,7 @@ function isCircuitBreakerStatus(status?: number): boolean {
}
function isCircuitOpen(providerID: string): boolean {
const state = providers.get(providerID)
const state = providers.get(providerKey(providerID))
if (!state?.circuitOpen) return false
const elapsed = Date.now() - state.circuitOpenAt