You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Before: every QueryAsync and ExecuteAsync went through a single
SemaphoreSlim(1, 1) at the CosmoKvConnection layer, so even
embarrassingly-parallel SELECTs ran strictly one-at-a-time on a
shared connection. The cosmokvd UDS rollout finding ("UDS savings
invisible at marivil stress") traced back here: the per-call
transport cost was dwarfed by queueing behind this single lock.
Three changes:
1. New AsyncReaderWriterLock — counting semaphore with 256 slots;
readers take 1, writers drain all. Mirrors the cosmokvd
TxnRegistry pattern. Fairness caveat: under sustained read load
a pending writer can wait indefinitely, but the mail-server
workload (read-heavy, short bursts of writes) doesn't hit this
in practice. Replace with a queue-fair lock if it ever bites.
2. Executor._kv → Executor._activeKv (AsyncLocal<IKvAccess?>). The
single mutable field that SetActiveAccess was writing depended
on the connection-level lock for race-freedom; AsyncLocal threads
each statement's value through its own async flow so concurrent
QueryAsync calls don't trample each other's routing. Shared
_defaultExprCache moves to ConcurrentDictionary for the same
concurrency reason.
3. CosmoKvConnection.QueryAsync now takes the READ lock; ExecuteAsync
/ BeginTransactionAsync / CommitAsync / RollbackAsync take the
WRITE lock. Reads run in parallel up to the rwlock's reader
capacity; writes still mutually exclude reads and other writers.
3 new xUnit tests in Phase29ConcurrentReadsTests verify:
- 16 concurrent SELECTs measurably faster than serial (proves
reads aren't serialised)
- 32 concurrent SELECTs filtered by bucket each return their
correct row count (proves AsyncLocal doesn't bleed across reads)
- Reader observing COUNT(*) during concurrent inserts never sees
a count-going-backwards (proves snapshot stability)
All 269 CosmoKv driver tests pass (266 prior + 3 new). Companion
deployment work (cosmokvd + mail-server) will follow once this
package indexes on NuGet.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments