What changed
- Start Oban unconditionally in the application supervision tree before the endpoint.
- Convert the GitHub issue syncer, GitHub release drop syncer, and feed drop syncer into Oban workers scheduled by
Oban.Plugins.Cron.
- Add
@reboot entries for syncers so they still run after boot, plus one-minute uniqueness guards to avoid duplicate boot and scheduled jobs in the same minute.
- Route the dashboard’s manual feed sync action through the feed worker instead of
Task.start/1.
- Remove the test-only drop syncer disable flag and the manual Oban startup from
test/test_helper.exs.
- Keep drop classification enqueueing independent from large language model configuration, so deterministic fallback classification still runs.
Why
The production error was not a missing model configuration problem. Feed ingestion can create drops and enqueue classification work even when model-backed agents are dormant, and that path needs Oban to be running.
Root cause
Hive.Drops.RssSyncer ran as a supervised timer process and could call Oban.insert/3 while the default Oban instance was unavailable. There were also other product syncers using their own timers or tasks, so background scheduling was split between Oban and application child processes.
Approach
Oban is now the single owner of product background execution. The syncers expose immediate sync_now entry points for tests and reuse the Oban worker perform/1 callbacks for scheduled work. One-source manual feed syncs enqueue the same worker with a drop_source_id.
Impact
Instances without model-backed agents can ingest feed drops without crashing and without making model calls. Scheduled sync behavior remains boot-time plus every fifteen minutes, but now the jobs are visible, retryable, and deduplicated through Oban.
Validation
mix compile --warnings-as-errors passed.
mix test passed with 806 tests.
- Focused tests passed for GitHub issue sync, GitHub release sync, feed sync, drop classification enqueueing, and the manual feed sync dashboard event.