Class RetentionWorker
Background worker that purges old rows from entities marked with RetainDaysAttribute. Runs once per 24 hours; on first start it runs after a short delay so library startup isn't blocked by a potentially long delete.
The entry list is live: entities registered after the worker was constructed
(the normal case — schema sync usually runs after CodeLogic.StartAsync()) are
picked up by TryRegister(Type, string), and the library starts the loop the first time
a [RetainDays] entity appears. Start() is idempotent.
Each purge pass runs DELETE FROM {table} WHERE {col} < @cutoff LIMIT batchSize
repeatedly until a pass deletes fewer rows than the batch size. The cutoff is computed
client-side as DateTime.UtcNow.AddDays(-days) and bound as a parameter — the server's
own clock is not consulted. That keeps individual transactions small
(friendly to InnoDB's undo log) while still converging on empty.
public sealed class RetentionWorker : IAsyncDisposable
- Inheritance
-
RetentionWorker
- Implements
- Inherited Members
Constructors
RetentionWorker(ConnectionManager, ILogger?, IEnumerable<Type>, string)
public RetentionWorker(ConnectionManager connectionManager, ILogger? logger, IEnumerable<Type> registeredEntities, string connectionId = "Default")
Parameters
connectionManagerConnectionManagerloggerILoggerregisteredEntitiesIEnumerable<Type>connectionIdstring
Properties
Entities
The entity types currently covered by a retention policy.
public IReadOnlyCollection<Type> Entities { get; }
Property Value
HasWork
Whether any registered entity has a retention policy to run.
public bool HasWork { get; }
Property Value
Registrations
The (entity, connection) pairs currently covered by a retention policy.
public IReadOnlyCollection<(Type Type, string ConnectionId)> Registrations { get; }
Property Value
Methods
DisposeAsync()
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources asynchronously.
public ValueTask DisposeAsync()
Returns
- ValueTask
A task that represents the asynchronous dispose operation.
RunOnceAsync(CancellationToken)
Runs one retention pass immediately over every registered entity and returns the number of rows removed. The background loop only wakes once a day behind an initial delay, so this is the entry point for an operator-triggered purge — and the only way to exercise the pass deterministically in a test.
public Task<int> RunOnceAsync(CancellationToken ct = default)
Parameters
Returns
Start()
Starts the background loop if there is work and it is not already running. Idempotent, and a no-op after disposal.
public void Start()
TryRegister(Type)
Adds entityType to the live entry list if it carries
RetainDaysAttribute. Returns true when it was added (i.e. it has a policy
and was not already registered), which is the caller's cue to Start().
Safe to call while the background loop is running.
public bool TryRegister(Type entityType)
Parameters
entityTypeType
Returns
TryRegister(Type, string)
As TryRegister(Type), but records the connection the entity was registered against so the purge runs against that database rather than the default.
public bool TryRegister(Type entityType, string connectionId)