Replica commit hardening: Reconcile sends its diff as one tagged commit; straggler guard inside the lock; real-server and budget pins (#91)
Some checks failed
CultMesh QUIC native / Build win32-x64 (push) Has been skipped
CultMesh QUIC native / Build linux-x64 (push) Has been skipped
CultMesh QUIC native / Release native binaries (push) Has been skipped
CultMesh portability and performance / ubuntu-latest reactive semantics and leases (push) Has been cancelled
CultMesh QUIC native / Verify committed binaries match SHA256SUMS (push) Has been cancelled

This commit is contained in:
Libby 2026-11-11 04:57:59 +00:00
commit abd1a92eb2
3 changed files with 214 additions and 7 deletions

View file

@ -245,14 +245,13 @@ namespace GameCult.Networking
return Apply(deliveryMode, new[] { message });
// The commit's other changes follow on this connection; the replica applies them as one commit.
// A straggler of a subscription that was ended, or never made, is not buffered.
if (!_deliveryModes.ContainsKey(message.SubscriptionId))
return Task.CompletedTask;
var held = (message.SubscriptionId, message.CommitId);
PendingCommit? pending;
lock (_commits)
{
if (Fault != null)
// A straggler of a subscription that was ended, or never made, is not buffered. Judged under the lock that
// Unsubscribe evicts under: a check before it could pass, lose the race to the eviction, and then buffer.
if (Fault != null || !_deliveryModes.ContainsKey(message.SubscriptionId))
return Task.CompletedTask;
var count = message.CommitCount!.Value;
var refusal = !_commits.TryGetValue(held, out pending)