Table of Contents

Class RetentionWorker

Namespace
CL.MySQL2.Services
Assembly
CL.MySQL2.dll

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

connectionManager ConnectionManager
logger ILogger
registeredEntities IEnumerable<Type>
connectionId string

Properties

Entities

The entity types currently covered by a retention policy.

public IReadOnlyCollection<Type> Entities { get; }

Property Value

IReadOnlyCollection<Type>

HasWork

Whether any registered entity has a retention policy to run.

public bool HasWork { get; }

Property Value

bool

Registrations

The (entity, connection) pairs currently covered by a retention policy.

public IReadOnlyCollection<(Type Type, string ConnectionId)> Registrations { get; }

Property Value

IReadOnlyCollection<(Type Type, string ConnectionId)>

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

ct CancellationToken

Returns

Task<int>

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

entityType Type

Returns

bool

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)

Parameters

entityType Type
connectionId string

Returns

bool