logo SERENITY
Game Systems Foundation
Search Results for

    Show / Hide Table of Contents

    Class StructuredStoreAchievementAdapter

    IAchievementStore implementation that translates every achievement operation into calls against the generic IStructuredStore contract, via AchievementRecordMapping. The single adapter every achievement backend (PlayerPrefs, local file, HTTP, Postgres, MySql, Mongo, Sqlite, custom) shares, so the revision policy is expressed exactly once instead of once per backend.

    Inheritance
    object
    StructuredStoreAchievementAdapter
    Implements
    IAchievementStore
    Inherited Members
    object.ToString()
    object.Equals(object)
    object.Equals(object, object)
    object.ReferenceEquals(object, object)
    object.GetHashCode()
    object.GetType()
    object.MemberwiseClone()
    Namespace: Serenity.Achievements.Infrastructure
    Assembly: Serenity.Achievements.Infrastructure.dll
    Syntax
    public class StructuredStoreAchievementAdapter : IAchievementStore
    Remarks

    Both writes go through UpsertIfBetterAsync(StoreTable, StructuredRecord, IReadOnlyList<string>, string, StructuredSortDirection, StructuredTrim, CancellationToken) keyed on KeyFieldsPlayerAndAchievement and compared on RevisionField descending: the caller (AchievementService) stamps a strictly increasing revision per row through AchievementRevisionClock, so "strictly better" always means "newer", and a screenshot attachment that finishes after a later state change loses instead of resurrecting it.

    An unlock write carrying no timestamp preserves the stored one: an upsert replaces ALL of a row's fields, so a caller that re-persists a record it did not read (a screenshot key, a platform-sync flag) would otherwise erase the moment the player earned the achievement — the one value the record exists to prove.

    Every failure from the underlying store is re-wrapped as AchievementStoreException (itself a PersistenceStoreException) so callers keep catching the achievement-specific type — not just PersistenceStoreException: a backend is free to surface a driver's own exception type, and one that escaped this boundary would reach the service as an unhandled failure instead of degraded persistence. OperationCanceledException always propagates unwrapped.

    Constructors

    StructuredStoreAchievementAdapter(IStructuredStore, StoreTable, StoreTable, ILogService)

    Initializes a new instance of the StructuredStoreAchievementAdapter class.

    Declaration
    public StructuredStoreAchievementAdapter(IStructuredStore store, StoreTable unlocksTable, StoreTable progressTable, ILogService logService)
    Parameters
    Type Name Description
    IStructuredStore store

    The generic structured store backing every achievement operation.

    StoreTable unlocksTable

    The table/collection unlock records are stored in.

    StoreTable progressTable

    The table/collection progress rows are stored in.

    ILogService logService

    Logging service used to report failures. May be null.

    Exceptions
    Type Condition
    ArgumentNullException

    Thrown when store is null.

    Methods

    ClearAsync(PlayerId, CancellationToken)

    Declaration
    public Task ClearAsync(PlayerId player, CancellationToken cancellationToken)
    Parameters
    Type Name Description
    PlayerId player
    CancellationToken cancellationToken
    Returns
    Type Description
    Task

    EnsureSchemaAsync(CancellationToken)

    Declaration
    public Task EnsureSchemaAsync(CancellationToken cancellationToken)
    Parameters
    Type Name Description
    CancellationToken cancellationToken
    Returns
    Type Description
    Task

    GetProgressAsync(PlayerId, CancellationToken)

    Declaration
    public Task<IReadOnlyList<AchievementProgress>> GetProgressAsync(PlayerId player, CancellationToken cancellationToken)
    Parameters
    Type Name Description
    PlayerId player
    CancellationToken cancellationToken
    Returns
    Type Description
    Task<IReadOnlyList<AchievementProgress>>

    GetUnlocksAsync(PlayerId, CancellationToken)

    Declaration
    public Task<IReadOnlyList<AchievementUnlockRecord>> GetUnlocksAsync(PlayerId player, CancellationToken cancellationToken)
    Parameters
    Type Name Description
    PlayerId player
    CancellationToken cancellationToken
    Returns
    Type Description
    Task<IReadOnlyList<AchievementUnlockRecord>>

    HealthCheckAsync(CancellationToken)

    Declaration
    public Task<bool> HealthCheckAsync(CancellationToken cancellationToken)
    Parameters
    Type Name Description
    CancellationToken cancellationToken
    Returns
    Type Description
    Task<bool>
    Remarks

    Never throws — passes through to the underlying HealthCheckAsync(CancellationToken), itself a never-throw contract.

    UpsertProgressAsync(PlayerId, AchievementProgress, CancellationToken)

    Declaration
    public Task UpsertProgressAsync(PlayerId player, AchievementProgress progress, CancellationToken cancellationToken)
    Parameters
    Type Name Description
    PlayerId player
    AchievementProgress progress
    CancellationToken cancellationToken
    Returns
    Type Description
    Task

    UpsertUnlockAsync(AchievementUnlockRecord, CancellationToken)

    Declaration
    public Task UpsertUnlockAsync(AchievementUnlockRecord record, CancellationToken cancellationToken)
    Parameters
    Type Name Description
    AchievementUnlockRecord record
    CancellationToken cancellationToken
    Returns
    Type Description
    Task

    Implements

    IAchievementStore
    In this article
    © 2026 Serenity. All Rights Reserved