fix: requests never wait on the relay settings or session-pin locks
Merged
AN
12h ago+2117+2117+0123456789012345678901234567890123456789-413-413-012345678901234567890123456789
A user request in OpenCode failed with Timed out acquiring native-relay lock for …/anthropic-auth-vault-settings.json under heavy CPU load: every request read the relay settings under the exclusive lock their writer uses, and a lock-wait timeout failed the request. Rule: a request never waits on or fails from bookkeeping I/O.
- Relay settings are read without a lock. The writer still serializes and now stamps the settings and the runtime token with one generation. Readers re-read (four tries, 10 ms apart) until both agree; both unstamped counts as legacy and is accepted. A pair that never agrees refuses that request locally (fixed non-retryable 400) and no token is sent. A racing reader/writer test proves an old URL never pairs with a new token.
- Session pins never hold a request. Requests waited up to 5 s for the routing-file lock and failed without it. Routes are now decided from the atomically published file without a lock; the pin change is published in the background under the lock (re-read, merge only that session, ownership fence, retry on failure, a queued assignment superseded by a clear is dropped, drained on dispose). A session reset deletes in memory at once and still reaches disk after contention.
- Proof that a healthy request takes no lock. On OpenCode 1, OpenCode 2 and Pi, a request with a valid token, known identity and ready roster records zero foreground lock acquisitions before dispatch, through an observer threaded into the lock calls (no global patching). A control per host shows an expired token still takes the real refresh lock. Credential-refresh and custody locks are unchanged.
Mutation rows: lock restored in the relay read, generation check disabled, route decided under a lease, superseded assignment published; all CAUGHT.
Summary by cubic
Fixes user requests that could time out or fail while waiting on relay settings or session-pin bookkeeping locks. Requests now complete without acquiring those locks; any bookkeeping is done in the background.
- Relay settings are read without a lock and validated via a shared generation stamp; readers retry briefly and refuse locally if a pair never agrees.
- Session-pin assignment and removal are queued and published in the background; routes are decided from the atomically published file without a lock. Tests drain queued publications before asserting on disk to remove timing flakiness.
- A lock observer distinguishes foreground and background-origin acquisitions, and the exported
NativeLockEventtype adds anacquiringevent; tests prove healthy requests take no foreground locks on OpenCode 1, OpenCode 2, and Pi. - Mutation controls catch any reintroduced reader locking or missing generation checks.