fix(reconcile): batch startup reconcile into fixed round trips, bound central work by QueryTimeout, retry failed site passes with back-off (review 2026-10-21 03/P-1)
This commit is contained in:
+31
@@ -341,6 +341,37 @@ public interface IDeploymentManagerRepository
|
||||
string configurationJson, string token, DateTimeOffset createdAtUtc, DateTimeOffset expiresAtUtc,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the deployed config snapshots of <paramref name="instanceIds"/> in ONE untracked
|
||||
/// query — the startup-reconcile gap read. Only the gap's ids should be passed: this is the
|
||||
/// read that materialises each snapshot's <c>ConfigurationJson</c>.
|
||||
/// </summary>
|
||||
/// <param name="instanceIds">Instances whose snapshots to read; duplicates are harmless.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>Instance id → snapshot, omitting instances with no snapshot (deleted race).</returns>
|
||||
Task<IReadOnlyDictionary<int, DeployedConfigSnapshot>> GetDeployedSnapshotsByInstanceIdsAsync(
|
||||
IReadOnlyCollection<int> instanceIds, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Batch form of <see cref="StagePendingIfAbsentAsync"/> for startup reconcile: expired
|
||||
/// pending rows for the candidates' instances are deleted, then every candidate whose
|
||||
/// instance has no LIVE pending row is inserted, all in one <c>SaveChanges</c>. A live row
|
||||
/// (an in-flight deploy, or the peer node's concurrent reconcile) is never superseded.
|
||||
/// Self-contained: commits its own writes.
|
||||
/// </summary>
|
||||
/// <param name="candidates">One new pending row per instance (later duplicates for the same instance are ignored).</param>
|
||||
/// <param name="nowUtc">"Now": rows with <c>ExpiresAtUtc <= nowUtc</c> are expired.</param>
|
||||
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
|
||||
/// <returns>
|
||||
/// Instance id → the instance's live pending row after the call: the candidate itself
|
||||
/// (reference-equal) when it was staged, otherwise the pre-existing live row, returned
|
||||
/// WITHOUT its <c>ConfigurationJson</c> (empty string). An instance whose candidate could not
|
||||
/// be staged and has no live row (e.g. the instance was deleted mid-reconcile) is omitted.
|
||||
/// </returns>
|
||||
Task<IReadOnlyDictionary<int, PendingDeployment>> StagePendingBatchIfAbsentAsync(
|
||||
IReadOnlyList<PendingDeployment> candidates, DateTimeOffset nowUtc,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
// Instance lookups for deployment pipeline
|
||||
/// <summary>
|
||||
/// Gets an instance by ID.
|
||||
|
||||
Reference in New Issue
Block a user