Skip to content

fix(reload): start, stop and rebuild sources on a config reload - #286

Merged
catinspace-au merged 1 commit into
mainfrom
fix/reload-sources
Nov 12, 2026
Merged

catinspace-au merged 1 commit into
mainfrom
fix/reload-sources

Conversation

@catinspace-au

Copy link
Copy Markdown
Contributor

The docker install runs one fetcher from one config file. The engine rewrites it when a source is added in the console. Before this fix, reload only stopped removed sources. Added sources logged "a restart is needed". Changed sources kept their old drivers.

A config reload applies source changes without a restart:

  • An added source starts fetching.
  • A removed source stops and frees its driver.
  • A changed source's old driver stops before rebuilding from the new settings, so a file tailer writes its last checkpoint.

Startup and reload share Scheduler::start_sources with a SourceFactory. Main's DriverFactory holds the old startup loop.

Each reload calls resolve_config_specs first, so drivers never get literal env: or vault: specs. A spec that does not resolve is retried every 30 s. New settings that do not build are logged and the old driver keeps running.

Changes are detected by hashing the source's own block with secret values exposed. PipelineState::reload_config is removed because it had no caller.

The container extractors and ingest listener from #134 are still built once at startup. Changing either still needs a restart, as documented in docs/internals.md.

Tests:

  • a_reload_starts_stops_and_rebuilds_sources_as_a_restart_would, one table over added, removed, changed and unchanged, including a resolved env: spec.
  • a_source_fingerprint_moves_with_its_own_settings_only over the production plan.
  • cargo nextest run -p dfe-fetcher: 985 passed on desktop-derek. The generics gate passes in the worktree and needs .git.

Refs #134

Added sources start on reload. Removed sources stop. A source changed under the same id is rebuilt from its new settings. Before, an added source only logged that a restart was needed.

Startup and reload build sources through Scheduler::start_sources and a SourceFactory. main's DriverFactory holds the old startup loop. Each reload runs resolve_config_specs first, so env: and vault: specs never reach a driver as literal values. A connection is rebuilt only when the hash of its own block, secrets included, changes.

A fetch task can sit in a flush or cursor commit outside its cancellation selects. Cancelling alone let two generations share a checkpoint. A replaced or removed generation moves to a stopping set. Its task is joined and its driver stopped, each within 10 s, before another starts.

The fetch task stops its own driver before it ends, replacing a drop guard that spawned the stop unawaited. A failed join still gets its driver stopped.

Generations whose shutdown is unconfirmed stay in the stopping set. The watcher retries every 30 s. The source restarts once the old generation is down.

RunningSources::shutdown waits for every fetch task, running or stopping, then stops every driver it holds. main calls it in place of its drain over running drivers. A custom shape can stop through the new RowSource::stop.

New settings that fail to build are logged. The old generation keeps running. Remove PipelineState::reload_config because it had no caller.

Refs #134
@catinspace-au
catinspace-au merged commit 16ab848 into main Nov 12, 2026
24 checks passed
@catinspace-au
catinspace-au deleted the fix/reload-sources branch November 12, 2026 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant