Multiple Sources & Coordinated Shutdown #11
Labels
No labels
agent
blocked
agent
new
agent
review
agent
working
complexity
high
complexity
low
priority
high
priority
low
priority
medium
risk
high
risk
low
risk
medium
type
bug
type
chore
type
feature
type
security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
tfks/logbus#11
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Source plugins are the ones that signal "I'm done" — when a source completes, its broadcast sender drops, which cascades downstream. With the current fan-in design (multiple upstream broadcast receivers merged into one mpsc), a single source completing just closes one forwarder task — the mpsc stays open as long as at least one forwarder is alive. So the data path accidentally works correctly for multiple sources today.
The real problem is shutdown semantics. Currently the pipeline has a single global shutdown signal (Ctrl+C). There's no concept of "all sources are done, begin draining." Consider a pipeline with two sources — a file source and a Kafka source:
What we want: the pipeline drains and shuts down when all sources have completed, without requiring an external signal. A single source finishing should not trigger shutdown.
Proposed Approach
Classify stages at build time. A source is any stage with no
inputs. Tag them:Source= no inputs.Sink= no downstream consumers.Transform= everything else.Source completion barrier. Collect source task handles separately:
Per-source status reporting. Sources should be able to report why they stopped:
This feeds into observability (section 3) — the dashboard can show which sources are still active and why each one stopped.
Interaction with Ctrl+C. The shutdown signal and source-completion barrier work together:
select!loops → barrier resolves → pipeline drainsEdge Cases
Infinite sources (e.g. Kafka, scheduler with no end): These never complete on their own. The pipeline stays alive until Ctrl+C. This is correct behavior — the barrier just waits for all sources, so one infinite source keeps the pipeline running.
Source restarts: A source that errors could optionally restart (with backoff) rather than counting as "completed." Config:
on_error: restart | complete | abort-pipeline.Dynamic source addition: Out of scope for now, but the barrier design doesn't preclude it — you'd add the new handle to the barrier set.
Migration Path
This is a pipeline-engine-only change. No Plugin trait modifications needed. Sources already exit their
start()method when done — we just need to track their handles separately and add the barrier logic inmain().