fix(site-secrets): prune secret_mirror_status rows of decommissioned or renamed nodes
Each node now re-writes its mirror-status row every SecretMirrorStatusRefreshInterval (10 min) as a heartbeat; SecretMirrorStatusReporter leaves off the health report and deletes any row not refreshed for SecretMirrorStatusStaleAfter (1 h, validated >= 2x the refresh). The delete is conditional on the checked_at it read, so a node that came back keeps its fresh row; a returning node re-writes its row on its first pass.
This commit is contained in:
@@ -1006,6 +1006,30 @@ public class SiteStorageService
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes <paramref name="nodeName"/>'s <c>secret_mirror_status</c> row, but only while it
|
||||
/// still carries <paramref name="checkedAtUtc"/> — so a row the node re-wrote after the caller
|
||||
/// read it (it came back, or refreshed just in time) is never deleted. The delete replicates
|
||||
/// like any other write.
|
||||
/// </summary>
|
||||
/// <param name="nodeName">The row key.</param>
|
||||
/// <param name="checkedAtUtc">The <c>checked_at</c> the caller read and judged stale.</param>
|
||||
/// <returns><see langword="true"/> when the row was deleted.</returns>
|
||||
public async Task<bool> DeleteSecretMirrorStatusIfUnchangedAsync(string nodeName, DateTimeOffset checkedAtUtc)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(nodeName);
|
||||
|
||||
await using var connection = OpenConnection();
|
||||
|
||||
await using var command = connection.CreateCommand();
|
||||
command.CommandText =
|
||||
"DELETE FROM secret_mirror_status WHERE node_name = @nodeName AND checked_at = @checkedAt";
|
||||
command.Parameters.AddWithValue("@nodeName", nodeName);
|
||||
command.Parameters.AddWithValue("@checkedAt", checkedAtUtc.ToUniversalTime().ToString("O"));
|
||||
|
||||
return await command.ExecuteNonQueryAsync() > 0;
|
||||
}
|
||||
|
||||
// ── Shared Script CRUD ──
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user