Class LoginServerSigningKeyService
Service for managing per-LoginServer HMAC signing keys. Uses EF Core compiled queries for the hot validation path and raw SQL for inserts.
public sealed class LoginServerSigningKeyService : BaseService<LoginServerSigningKeyEntity>, ILoginServerSigningKeyService
- Inheritance
-
LoginServerSigningKeyService
- Implements
- Inherited Members
Constructors
LoginServerSigningKeyService(INpgsqlDbContextFactory)
public LoginServerSigningKeyService(INpgsqlDbContextFactory dbContextFactory)
Parameters
dbContextFactoryINpgsqlDbContextFactory
LoginServerSigningKeyService(INpgsqlDbContextFactory, int)
public LoginServerSigningKeyService(INpgsqlDbContextFactory dbContextFactory, int keyOverlapWindowDays)
Parameters
dbContextFactoryINpgsqlDbContextFactorykeyOverlapWindowDaysint
Properties
KeyOverlapWindowDays
Verification overlap window (in days) during which rotated-out keys are still kept in the table so in-flight tokens signed before rotation can be validated. The value is injected at construction time and defaults to 7 days.
public int KeyOverlapWindowDays { get; }
Property Value
Methods
DeleteAsync(long, CancellationToken)
Deletes the signing key for a specific LoginServer. Called during LoginServer shutdown or key rotation.
public Task<DatabaseResult> DeleteAsync(long loginServerId, CancellationToken cancellationToken = default)
Parameters
loginServerIdlongcancellationTokenCancellationToken
Returns
FetchByIdAsync(long, CancellationToken)
Fetches a signing key by its token-embedded database ID.
public Task<DatabaseResult<LoginServerSigningKeyData>> FetchByIdAsync(long signingKeyId, CancellationToken cancellationToken = default)
Parameters
signingKeyIdlongcancellationTokenCancellationToken
Returns
FetchByLoginServerIdAsync(long, CancellationToken)
Fetches the signing key for a specific LoginServer. Called by WorldServers and SceneServers during token validation.
public Task<DatabaseResult<LoginServerSigningKeyData>> FetchByLoginServerIdAsync(long loginServerId, CancellationToken cancellationToken = default)
Parameters
loginServerIdlongcancellationTokenCancellationToken
Returns
UpsertAsync(long, byte[], CancellationToken)
Upserts the active signing key for the specified LoginServer.
DUAL-LAYER EXECUTION CONTROL:
Outer layer — ExecuteWriteAsync retry loop (defined in BaseService): Wraps the entire operation in a configurable retry policy (up to 3 attempts with exponential backoff). If the inner execution strategy or transaction fails transiently (e.g. serialisation error, deadlock victim), the outer loop retries from scratch — creating a fresh DbContext and re-entering the execution strategy.
Inner layer — execution strategy with explicit transaction: The DbContext.Database.CreateExecutionStrategy() provides Npgsql's built-in retry-on-serialisation-failure inside the transaction scope. The explicit transaction itself ensures atomicity of the deactivate-INSERT pair: if the INSERT fails, the UPDATE is rolled back and no key is lost. The partial UNIQUE index on (login_server_id) WHERE is_active=true additionally serialises concurrent rotations.
This dual-layer design was chosen because the outer retry handles connection-level failures (pool exhaustion, DNS flake, TCP reset) while the inner strategy handles database-level contention (serialisation failures, unique-index violations). Each layer retries at its own granularity without conflating the two failure modes.
public Task<DatabaseResult<LoginServerSigningKeyData>> UpsertAsync(long loginServerId, byte[] hmacKey, CancellationToken cancellationToken = default)
Parameters
loginServerIdlonghmacKeybyte[]cancellationTokenCancellationToken