Repository navigation
feat(server): keep live sessions running through engine rollover - #3696
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Warden security clearance: clear. No blocking findings (security or desktop↔den sync) in this diff (48c27744bc1e7e49eb82bc47e37c67c3fbf09e8a). Automated clearance satisfies the required-review gate only — a human still reviews and merges. Analysis run
There was a problem hiding this comment.
Warden security clearance: clear. No blocking findings (security or desktop↔den sync) in this diff (8d4e4242012f6034c96e4595d47d18b4c5c37957). Automated clearance satisfies the required-review gate only — a human still reviews and merges. Analysis run
A provider sync pass disposes the managed engine when provider config
changes, because the engine only reads provider config (models, npm,
options.baseURL) from OPENCODE_CONFIG when it builds an instance. If a
pass reported a change on unchanged upstream state, that dispose would
repeat on every 5-minute interval and tear down whatever is running.
The existing coverage only exercised an empty provider list and a single
follow-up pass. Extend it: materialize a provider carrying the full
config surface, then assert five further passes over a byte-identical
snapshot report "noop", perform no additional dispose, and do not
re-deliver the credential (the auth push is fingerprint-guarded).
Also record why a provider config delta still reloads at all. Credentials
reach a live engine through PUT /auth/{providerID}, but provider config
has no live path: PATCH /config, the only endpoint accepting it, performs
the same instance dispose as POST /instance/dispose. Verified against
opencode 1.18.15 — PATCH /config and POST /instance/dispose both drop an
open /event stream, while GET /config and PUT /auth/{id} leave it intact.
A reload that lands while sessions are running has only had bad options: dispose and abort the runs, or defer and leave config stale until the engine idles. Provider config in particular cannot be applied any other way -- the engine reads it when it builds an instance. Add an opt-in third option. When a reload is needed and the engine is busy, spawn a standby with the new config, point the server at it once it answers, and keep the old engine alive only until its runs finish. Idle engines still reload in place, so steady state stays one process. - ServerConfig.engineRollover (env OPENWORK_ENGINE_ROLLOVER), off by default - engine-pool.ts: generations, config fingerprint so a repeated no-op reload never spawns, single-flight with latest-wins coalescing, standby readiness probe before any flip, synchronous pointer flip, drain monitor that closes the old engine once idle, and a grace period after which remaining sessions are aborted - Cap of one primary plus one draining engine: changes arriving mid-drain coalesce rather than stacking processes - reloadOpencodeEngine dispatches to the pool when enabled; the existing in-place dispose is unchanged and still the default Tunable via OPENWORK_ENGINE_DRAIN_TIMEOUT_MS, _DRAIN_POLL_MS, _MIN_SPAWN_INTERVAL_MS, _ABORT_SETTLE_MS.
8d4e424 to
139c70c
Compare
There was a problem hiding this comment.
Warden security clearance: clear. No blocking findings (security or desktop↔den sync) in this diff (139c70c4fa0e496340231ebd4a7b984db1db80e7). Automated clearance satisfies the required-review gate only — a human still reviews and merges. Analysis run
Problem
Provider, plugin, agent, permission, and other build-time OpenCode configuration changes currently dispose the managed engine. Deferring those updates while work is active protects live sessions, but leaves new configuration unavailable until every run has finished.
Change
Verification
apps/server: 667 passed, 8 skippedapps/app: 707 passedOPENWORK_EVAL_ENGINE_ROLLOVER_SPEC