public sealed class LedgerBridgeDoc 28's economy on doc 27's ledger: applied in the frame, written down afterwards, and never awaited.
Remarks
The two sides do not have the same shape and could not. IEconomyLedger is synchronous because it is called from a rule, mid-frame, several times per hit; ILedger is a database round trip. ADR-016's rule — "Orleans is asked, not awaited" — makes a blocking adapter between them the one implementation that is definitely wrong, and it is also the obvious one.
So the in-memory projection is authoritative for the frame and the database is the audit trail. That is not optimism: ADR-021's lease says exactly one realm may write a player, so the projection cannot disagree with the database while the lease is held. Every accepted intent goes into an outbox, the realm drains it and posts it through RealmDirectory, and the answer arrives at a later PreUpdate.
⚠ A Superseded is not an undo. ADR-021 says a realm that loses its lease mid-combat "keeps simulating, buffers durable mutations as ledger intents, and either flushes them when the lease returns or hands them to the new holder". So a superseded write stays in the outbox and is re-drained; rolling the projection back would take an item off somebody who is still holding it.
⚠ An Insufficient or Unbalanced answer is a defect, not a refusal. The projection checked both before the intent was ever queued, so the database disagreeing means the two have diverged — which is the one thing the lease exists to prevent. It is counted and surfaced rather than swallowed, because a bridge that quietly dropped those would be a bridge that loses items in a way nobody can reproduce.
⚠ Nothing here writes a gameplay PlayerId. Every account crosses through IGameplayIdentity into a PlayerKey — see that type for why a realm-scoped integer in a durable row is somebody else next week.
Fields and properties (7)
public const string RestoreAccountThe world account a restored balance is transferred out of.
public long LeaseEpochThe epoch this realm holds.
public bool HoldsLeaseWhether the lease is still this realm's.
public int PendingHow many writes are waiting to be drained or answered.
public int DivergencesHow many answers said the projection and the database disagree. Never anything but zero.
public int DeduplicatedHow many posts were recognised from the outbox rather than from the projection.
public BridgeRefusal LastRefusalWhy the last Post was refused.
Events (1)
public Action<PendingWrite, LedgerResult>? DivergedRaised when the database refuses a write the projection had accepted.
Methods (8)
public LedgerBridge(IGameplayIdentity identity, IEconomyLedger projection, long leaseEpoch)Makes one over a projection.
public EconomyResult Post(EconomyIntent intent)Applies an intent here and queues it to be written down.
public long Balance(EconomyAccount account, DefId asset)What an account holds of something.
public bool Restore(EconomyAccount account, DefId asset, long amount)Puts a saved balance into the projection without queueing a write.
public ImmutableArray<PendingWrite> Drain()Takes everything waiting to be written down.
public bool Settle(IdempotencyKey key, LedgerResult result)Applies what the database said about a write.
public void Renew(long epoch)Says the lease came back, at a new epoch, so the outbox may be flushed again.
public void Supersede()Says the lease is gone.
Used by (4)
- ShardMmo.Soak
- SoakMmo.Soak
- HousekeepingTestsVixen.Live.Gameplay.Tests
- LedgerBridgeTestsVixen.Live.Gameplay.Tests