Skip to content

work-unit: control plane — output lifecycle status wiring #1416

Closed

Description

@strawgate

work-unit: control plane — output lifecycle status wiring

Purpose

Wire output-side lifecycle truth into the shared control-plane model after the shared status types and probe semantics are established.

This batch is intentionally downstream of #1414 and #1413: it makes sink startup, degradation, retry pressure, fatal failure, and shutdown visible through the common status model without attempting the full exporter redesign in one pass.

Repo footprint

  • crates/logfwd/src/worker_pool.rs
  • crates/logfwd-output/src/sink.rs
  • representative concrete sinks in crates/logfwd-output/src/
  • crates/logfwd/tests/ and crates/logfwd-output/tests/

In scope

# Type Why included
#1306 architecture sink-side lifecycle is part of the shared control-plane substrate
#1312 architecture output semantics need explicit runtime status, especially around retries and failures
#1313 architecture file appender should participate in the same shared lifecycle/status model

Related metas / phases

  • should follow #1414 shared status model and #1413 probe truth
  • adjacent behavior work: #1443 retry/status helpers and #1272 fanout delivery contract bugs
  • temporary cleanup-wave coordination only: #1450

Non-goals

  • no fanout atomicity redesign (that stays in #1272 / #1312)
  • no retry/backoff architecture rewrite beyond surfacing status honestly
  • no restoration of missing sink types
  • no broad output config work

Done when

  • worker-pool and sink lifecycle states feed the shared status model
  • startup, degraded/retrying, failed, and stopping sink states are visible in diagnostics
  • readiness reflects the chosen sink-health policy rather than defaulting to healthy forever
  • representative sink / worker-pool tests cover startup, retry pressure, fatal failure, and clean shutdown

Activity

  1. added
    enhancementNew feature or request
    productionRequired for production readiness
    P2: mediumMinor bug, missing validation, metric inaccuracy
    work-unitScheduling ticket for one agent run
    architectureSystemic design improvements that eliminate classes of bugs
    on Apr 6, 2026
  2. github-actions commented on Apr 6, 2026

    @github-actions
    Contributor

    tl;dr: Outcome A — Ready for implementation. The core blocker is already concrete: output lifecycle/readiness cannot be wired correctly because worker-pool acks collapse sink outcomes to success: bool, and readiness is currently independent of sink health.

    Recommendation

    Implement this issue as a focused protocol+diagnostics wiring change in worker_pool + pipeline + diagnostics + output tests: carry sink/lifecycle state through AckItem, update per-sink diagnostics, and gate readiness by explicit sink-health policy.

    Findings
    1. Ack protocol is too lossy for lifecycle truth

      • crates/logfwd/src/worker_pool.rs:82-87
        pub struct AckItem { ... pub success: bool, ... }
      • No sink identity or lifecycle stage (startup/degraded/retrying/failed/stopping) is propagated.
    2. Pipeline currently records output failure against pipeline name, not sink name

      • crates/logfwd/src/pipeline.rs:979
        self.metrics.output_error(self.name.as_str());
      • But outputs are keyed by configured output names:
        • crates/logfwd/src/pipeline.rs:331-337, 342-349 (metrics.add_output(&output_name, ...))
      • And output_error matches by output name only:
        • crates/logfwd-io/src/diagnostics.rs:197-203.
    3. Readiness does not use sink health at all

      • crates/logfwd-io/src/diagnostics.rs:553-555
        let ready = !self.pipelines.is_empty();
      • This is explicitly documented as not data-flow/sink-health based (545-552).
    4. Known in-code limitation confirms this gap

      • crates/logfwd/src/pipeline.rs:2382-2383
        // Per-sink error tracking ... not currently supported by the pool's AckItem protocol
    Verification

    Ran targeted existing readiness tests:

    cargo test -p logfwd-io ready_endpoint -- --nocapture

    Output:

    • test_ready_endpoint_no_pipelines_returns_503 ... ok
    • test_ready_endpoint_with_pipeline_returns_200 ... ok

    This confirms current /ready behavior is purely pipeline-registration based.

    Detailed Action Plan (mechanical)
    1. Extend worker ack semantics to carry sink lifecycle/status

      • File: crates/logfwd/src/worker_pool.rs (AckItem at 82-105, process_item at 565+, worker_task at 459+)
      • Exact changes:
        1. Add fields to AckItem:
          • sink_name: String (or interned/static variant)
          • outcome: OutputOutcome (new enum)
          • optional retry metadata (attempts, last_retry_after_ms)
        2. Replace (bool, send_latency_ns) return from process_item with structured outcome (OutputOutcome) + latency.
        3. Map send paths explicitly:
          • SendResult::Ok → Delivered
          • RetryAfter/... with eventual success/failure → RetriedThenDelivered / RetryExhausted
          • Rejected → PermanentFailure
          • timeout/panic/cancel/drain force-stop → FatalFailure / StoppingAborted
    2. Fix pipeline wiring to per-sink metrics and lifecycle

      • File: crates/logfwd/src/pipeline.rs (apply_pool_ack at 965-982)
      • Exact changes:
        1. Replace output_error(self.name.as_str()) with sink-name-aware update from AckItem.
        2. Update ack handling to record degraded/retrying/failure counters/state (not only success/fail).
        3. Preserve existing checkpoint semantics (ack_all_tickets) while enriching diagnostics state.
    3. Add sink lifecycle/readiness model to diagnostics

      • File: crates/logfwd-io/src/diagnostics.rs
      • Exact changes:
        1. Extend PipelineMetrics with sink-status storage (per output): starting|ready|degraded|failed|stopping + timestamps.
        2. Extend /api/pipelines payload to expose per-output lifecycle + retry pressure counters.
        3. Update /ready (serve_ready at 553-568) to evaluate configured sink-health policy instead of only !pipelines.is_empty().
    4. Introduce configurable readiness policy (minimal explicit policy)

      • Files:
        • crates/logfwd-config/src/... (server/output readiness config model)
        • crates/logfwd/src/main.rs and/or pipeline bootstrap wiring
      • Exact changes:
        1. Add policy enum (example):
          • AnySinkReady (lenient)
          • AllSinksReady (strict)
          • optional AllowDegradedFor: Duration
        2. Thread policy into diagnostics server readiness evaluation.
    5. Tests to write (representative and mechanical)

      • crates/logfwd/src/worker_pool.rs tests module
        • pattern: existing async worker_pool unit tests
        • add assertions for startup → retry/degraded → fatal → stopping transitions via new AckItem.outcome.
      • crates/logfwd/src/pipeline.rs tests (near test_async_fanout_output_errors_only_increment_failing_output)
        • assert per-sink error/lifecycle attribution is correct (not pipeline-name fallback).
      • crates/logfwd-io/src/diagnostics.rs tests (near ready endpoint tests at 1634+)
        • add readiness policy tests:
          • no healthy sinks => 503
          • degraded-within-policy => 200 (if configured)
          • failed sink under strict policy => 503
    6. Verification commands

      • cargo test -p logfwd-io diagnostics::tests::test_ready_endpoint_no_pipelines_returns_503 diagnostics::tests::test_ready_endpoint_with_pipeline_returns_200
      • cargo test -p logfwd --lib worker_pool
      • cargo test -p logfwd --lib pipeline
      • final gate: just ci
    Related Items
    Type Link Relevance
    Issue #1416 This work-unit
    Issue #1306 Shared control-plane substrate context (from issue scope)
    Issue #1312 Output/runtime status architecture context (from issue scope)
    Issue #1313 File-appender lifecycle integration context (from issue scope)
    Issue #1315 Parent execution slice
    Issue #1357 Adjacent sink-result semantics scope boundary
    PR #701 Introduced async worker pool + async sinks foundation
    PR #745 Follow-up fixes; includes retry/ack behavior refinements
    File crates/logfwd/src/worker_pool.rs:82 Ack protocol currently too coarse (success: bool)
    File crates/logfwd/src/pipeline.rs:979 Error attribution currently uses pipeline name
    File crates/logfwd-io/src/diagnostics.rs:553 /ready currently ignores sink health

    Note

    🔒 Integrity filtering filtered 7 items

    Integrity filtering activated and filtered the following items during workflow execution.
    This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.


    What is this? | From workflow: Issue Triage

    Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

  3. strawgate commented on Apr 6, 2026

    @strawgate
    OwnerAuthor

    The first pure-seam extraction batch under this work-unit is now #1439 (logfwd-output sink and fanout health policy).

    That gives us a merge-safe local slice before the broader sink lifecycle wiring work lands.

  4. added
    component:output/commonCross-cutting output behavior spanning multiple sinks
    component:pipelinePipeline orchestration, batching, runtime flow, and worker coordination
    on Apr 6, 2026
  5. changed the title [-]work-unit: logfwd-output + worker_pool — sink lifecycle, degradation, and failure wiring[/-] [+]work-unit: control plane — output lifecycle status wiring[/+] on Apr 6, 2026
  6. strawgate commented on Apr 7, 2026

    @strawgate
    OwnerAuthor

    Resolved by PRs #1454, #1480, #1505. Verified: OutputHealthEvent reducer, per-worker health tracking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2: mediumMinor bug, missing validation, metric inaccuracyarchitectureSystemic design improvements that eliminate classes of bugscomponent:diagnosticsDiagnostics endpoints, dashboard, health, probes, and trace explorercomponent:output/commonCross-cutting output behavior spanning multiple sinkscomponent:pipelinePipeline orchestration, batching, runtime flow, and worker coordinationenhancementNew feature or requestproductionRequired for production readinesswork-unitScheduling ticket for one agent run

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions