feat(archreview #13): apply per-instance ResilienceConfig from the deploy artifact
The DriverInstance.ResilienceConfig column was authored in AdminUI, persisted to the entity, and serialized into the deployment artifact by ConfigComposer — but the runtime read path dropped it: DriverInstanceSpec didn't carry it and the invoker factory always passed null, so every driver got tier defaults regardless of its configured overrides (a silent dead-config gap — #10's residual sub-finding). Read-path plumbing (write side was already complete): - DriverInstanceSpec gains ResilienceConfig; DeploymentArtifact.TryReadSpec reads the column. - IDriverCapabilityInvokerFactory.Create takes resilienceConfigJson; DriverHostActor.SpawnChild threads spec.ResilienceConfig; the concrete factory parses it (ParseOrDefaults, layering on the tier), logs any parse diagnostic (never throws), and builds the invoker with the merged options. - Invalidate-on-change: the pipeline cache keys on (instance, host, capability) and ignores options on a hit, so Create() now Invalidate()s the instance's cached pipelines first (no-op on first spawn) — a respawn with changed options rebuilds them. - DriverSpawnPlanner treats a ResilienceConfig change as a stop+respawn (the invoker/options are bound to the child at spawn); a pure DriverConfig change stays an in-place delta (no reconnect). - Host DI passes a logger to the factory for the parse diagnostic. Verification (deterministic): factory Create applies a retryCount:0 override to actual execution (control test proves tier default retries), invalidates the instance's cache on re-create (scoped — sibling survives), malformed config logs+falls-back; planner respawns on ResilienceConfig change (incl null→json) and stays delta on a pure config change; artifact parse carries/omits the column. Core.Tests 243 (+5), Runtime.Tests 363 (+5), Host builds clean.
This commit is contained in:
@@ -18,7 +18,8 @@ public sealed record DriverInstanceSpec(
|
||||
string DriverType,
|
||||
bool Enabled,
|
||||
string DriverConfig,
|
||||
string? ClusterId = null);
|
||||
string? ClusterId = null,
|
||||
string? ResilienceConfig = null);
|
||||
|
||||
/// <summary>How a node should scope a deployment artifact to its own ClusterId.</summary>
|
||||
public enum ClusterFilterMode
|
||||
@@ -167,6 +168,9 @@ public static class DeploymentArtifact
|
||||
|| enEl.GetBoolean();
|
||||
var config = ReadString(el, "DriverConfig");
|
||||
var clusterId = ReadString(el, "ClusterId");
|
||||
// Per-instance resilience overrides (DriverInstance.ResilienceConfig column). Optional/nullable —
|
||||
// absent means tier defaults; layered onto the tier by DriverResilienceOptionsParser at spawn.
|
||||
var resilienceConfig = ReadString(el, "ResilienceConfig");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(id) || string.IsNullOrWhiteSpace(type)) return null;
|
||||
|
||||
@@ -177,7 +181,8 @@ public static class DeploymentArtifact
|
||||
DriverType: type!,
|
||||
Enabled: enabled,
|
||||
DriverConfig: config ?? "{}",
|
||||
ClusterId: clusterId);
|
||||
ClusterId: clusterId,
|
||||
ResilienceConfig: resilienceConfig);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user