fix(s3/lifecycle): align walker dispatch error label to RPC_ERROR

Mirrors the same gemini-flagged inconsistency on the walker side as
the Phase 6 PR fixed on the replay side: streaming uses "RPC_ERROR"
for transport-class failures, so the walker should too. Also folds
the nil-response case under RPC_ERROR rather than a new label —
operationally it's the same class of failure (server returned no
usable response), no point splitting the metric for it.
This commit is contained in:
Chris Lu
2026-05-12 11:42:41 -07:00
parent 87f29874c3
commit ed5fa1926d
@@ -59,14 +59,16 @@ func (d *WalkerDispatcher) Delete(ctx context.Context, action *engine.CompiledAc
kindLabel := action.Key.ActionKind.String()
resp, err := d.Client.LifecycleDelete(ctx, req)
if err != nil {
stats.S3LifecycleDispatchCounter.WithLabelValues(action.Bucket, kindLabel, "TRANSPORT_ERROR").Inc()
// "RPC_ERROR" matches the streaming dispatcher and processMatches
// labels so transport-class failures aggregate under one key.
stats.S3LifecycleDispatchCounter.WithLabelValues(action.Bucket, kindLabel, "RPC_ERROR").Inc()
return fmt.Errorf("walker dispatch %s/%s %s: %w", action.Bucket, objectPath, action.Key.ActionKind, err)
}
if resp == nil {
// A misbehaving server stub returning (nil, nil) would panic on
// the switch below. Surface as an error so the walk halts at
// this entry, preserving the in-flight cursor's correctness.
stats.S3LifecycleDispatchCounter.WithLabelValues(action.Bucket, kindLabel, "NIL_RESPONSE").Inc()
// the switch below. Bucket under RPC_ERROR rather than a new
// label — operationally it's the same class of failure.
stats.S3LifecycleDispatchCounter.WithLabelValues(action.Bucket, kindLabel, "RPC_ERROR").Inc()
return fmt.Errorf("walker dispatch %s/%s %s: nil response", action.Bucket, objectPath, action.Key.ActionKind)
}
stats.S3LifecycleDispatchCounter.WithLabelValues(action.Bucket, kindLabel, resp.Outcome.String()).Inc()