.vbw-planning/milestones/ui-fixes-and-smart-scraping/phases/02-feed-reliability/04-PLAN.md
Add a consecutive_fetch_failures counter to Source. Increment on every failed fetch, reset on success. When counter reaches 5, auto-pause the source. Integrate with the existing health status system and notify the user.
Files to create:
db/migrate/TIMESTAMP_add_consecutive_fetch_failures_to_sources.rbSteps:
consecutive_fetch_failures integer column to sourcemon_sources, default: 0, null: falseadd_index :sourcemon_sources, :consecutive_fetch_failures, where: "consecutive_fetch_failures > 0", name: "index_sources_on_consecutive_failures"Files to modify:
lib/source_monitor/fetching/feed_fetcher/source_updater.rbSteps:
update_source_for_success: add consecutive_fetch_failures: 0 to the attributes hash (reset on success)update_source_for_not_modified: add consecutive_fetch_failures: 0 to the attributes hash (304 is a success)update_source_for_failure: add consecutive_fetch_failures: source.consecutive_fetch_failures.to_i + 1 to the attrs hashupdate_source_for_failure, check if consecutive_fetch_failures >= 5 and trigger auto-pause if soFiles to modify:
lib/source_monitor/fetching/feed_fetcher/source_updater.rbSteps:
check_consecutive_failure_auto_pause! called after source.update! in update_source_for_failureCONSECUTIVE_FAILURE_PAUSE_THRESHOLD = 5)auto_paused_until to Time.current + auto_pause_cooldown (use config value from SourceMonitor.config.health.auto_pause_cooldown_minutes)auto_paused_at to Time.currenthealth_status to "auto_paused"health_status_changed_at to Time.currentbackoff_until to match auto_paused_untilnext_fetch_at to match auto_paused_untilsource.update_columns(...) for this second update (avoids callbacks, fast)auto_paused_until.nil? || auto_paused_until.past?)Files to modify:
lib/source_monitor/fetching/feed_fetcher/source_updater.rbSteps:
SourceMonitor::LogEntry.create! with level: "warning", message describing the auto-pauseSourceMonitor::Realtime.broadcast_toast(message: "Source '#{source.name}' has been auto-paused after #{threshold} consecutive failures.", level: :warning) if the method existsSourceMonitor::Realtime.broadcast_source(source) to update the UI with the new auto_paused statusFiles to modify:
lib/source_monitor/health/source_health_monitor.rbSteps:
determine_status, check consecutive_fetch_failures as an additional signal:
source.consecutive_fetch_failures.to_i >= 5 AND source is auto-paused, status is "auto_paused" (this should already work since Task 3 sets auto_paused_until)consecutive_fetch_failures is also resetshould_resume?), ensure consecutive_fetch_failures is reset to 0 when auto_paused_until is clearedattrs[:consecutive_fetch_failures] = 0 in the resume block alongside clearing auto_paused_untilFiles to create:
test/lib/source_monitor/fetching/consecutive_failures_test.rbFiles to modify:
test/lib/source_monitor/fetching/source_updater_test.rbtest/lib/source_monitor/health/source_health_monitor_test.rbSteps:
consecutive_fetch_failures increments on every fetch failureconsecutive_fetch_failures resets to 0 on any successful fetch (200 or 304)auto_paused_until, health_status, backoff_until, next_fetch_atbin/rubocop passes with zero offensesbin/rails test passes