public sealed class SqlPersistenceThe shipped one: ADO.NET, PostgreSQL dialect, one transaction per intent.
Remarks
⚠ A DbDataSource rather than a driver package, and that is a deliberate line. Doc 27 M-Q3 says one implementation, and this is it — the SQL in Schema is Postgres and does not pretend otherwise. What this assembly does not do is reference Npgsql: the caller constructs NpgsqlDataSource.Create(connectionString) and hands it over. The gain is that a game engine does not pin a database driver's version for every game that links it, and that connection pooling, logging, tracing and TLS are configured where the deployment already configures them rather than through options this layer would have to mirror.
⚠ What a test can and cannot say about this class. Every semantic doc 27 § Persistence names — idempotency, the fence, conservation — is asserted against MemoryPersistence on every push, because those are properties of the semantics. Whether a real PostgreSQL accepts these statements is a question only a real PostgreSQL answers, and it belongs on the same nightly leg as the kind and Docker placement backends. That is the same honest split IClusterApi makes.
Fields and properties (3)
public IAccountRepository AccountsAccounts.
public IPlayerRepository PlayersCharacters.
public ILedger LedgerThe journal.
Methods (17)
public SqlPersistence(DbDataSource source, bool ownsSource = false)The shipped one: ADO.NET, PostgreSQL dialect, one transaction per intent.
public Task<int> MigrateAsync(CancellationToken cancellation)Brings the schema up to date, and says nothing if it already is.
public ValueTask DisposeAsync()Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously.
public Task<AccountRecord?> ReadAsync(Guid id, CancellationToken cancellation)Reads an account.
public Task<AccountRecord?> ByHandleAsync(string handle, CancellationToken cancellation)Finds the account an authority's handle maps to.
public Task<(AccountRecord Account, bool Created)> EnsureAsync(string handle, DateTimeOffset now, CancellationToken cancellation)Makes an account for a handle that has none.
public Task<WriteOutcome> SetSuspendedAsync(Guid id, bool suspended, CancellationToken cancellation)Suspends an account, or lifts it.
public Task<PlayerRecord?> ReadAsync(PlayerKey key, CancellationToken cancellation)Reads a character.
public Task<IReadOnlyList<PlayerRecord>> ForAccountAsync(Guid account, CancellationToken cancellation)Every character on an account — the list the gate serves at character select.
public Task<WriteOutcome> CreateAsync(PlayerRecord record, CancellationToken cancellation)Makes a character.
public Task<WriteOutcome> WriteAsync(PlayerRecord record, CancellationToken cancellation)Writes a character, if the writer still holds the lease.
public Task<long> FenceAsync(PlayerKey key, CancellationToken cancellation)The epoch this character's row will accept a write at or above.
public Task<LedgerResult> AppendAsync(LedgerIntent intent, CancellationToken cancellation)Applies an intent, or recognises that it already was.
public Task<long> BalanceAsync(LedgerAccount account, AssetId asset, CancellationToken cancellation)What an account holds of an asset.
public Task<IReadOnlyDictionary<AssetId, long>> HoldingsAsync(LedgerAccount account, CancellationToken cancellation)Everything an account holds.
public Task<IReadOnlyList<LedgerEntry>> HistoryAsync(LedgerQuery query, CancellationToken cancellation)Reads the journal.
public Task<IReadOnlyList<LedgerDiscrepancy>> ReconcileAsync(CancellationToken cancellation)Checks the running balances against the journal they were derived from.