source_monitor 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/rails-audit.md +77 -0
  3. data/CHANGELOG.md +50 -0
  4. data/CLAUDE.md +2 -2
  5. data/Gemfile.lock +7 -20
  6. data/RAILS_AUDIT.md +424 -0
  7. data/VERSION +1 -1
  8. data/app/assets/builds/source_monitor/application.css +4 -24
  9. data/app/assets/builds/source_monitor/application.js +57 -89
  10. data/app/assets/builds/source_monitor/application.js.map +4 -4
  11. data/app/assets/javascripts/source_monitor/application.js +3 -6
  12. data/app/assets/javascripts/source_monitor/controllers/dropdown_controller.js +6 -86
  13. data/app/assets/javascripts/source_monitor/controllers/filter_submit_controller.js +13 -0
  14. data/app/assets/javascripts/source_monitor/controllers/modal_controller.js +56 -0
  15. data/app/assets/javascripts/source_monitor/controllers/notification_controller.js +3 -13
  16. data/app/components/source_monitor/application_component.rb +10 -0
  17. data/app/components/source_monitor/filter_dropdown_component.rb +62 -0
  18. data/app/components/source_monitor/icon_component.rb +140 -0
  19. data/app/components/source_monitor/status_badge_component.html.erb +8 -0
  20. data/app/components/source_monitor/status_badge_component.rb +96 -0
  21. data/app/controllers/concerns/source_monitor/sanitizes_search_params.rb +4 -0
  22. data/app/controllers/concerns/source_monitor/set_source.rb +13 -0
  23. data/app/controllers/source_monitor/application_controller.rb +17 -0
  24. data/app/controllers/source_monitor/bulk_scrape_enablements_controller.rb +6 -10
  25. data/app/controllers/source_monitor/dashboard_controller.rb +5 -1
  26. data/app/controllers/source_monitor/import_history_dismissals_controller.rb +1 -1
  27. data/app/controllers/source_monitor/import_sessions_controller.rb +30 -9
  28. data/app/controllers/source_monitor/item_scrapes_controller.rb +70 -0
  29. data/app/controllers/source_monitor/items_controller.rb +2 -69
  30. data/app/controllers/source_monitor/source_bulk_scrapes_controller.rb +1 -4
  31. data/app/controllers/source_monitor/source_favicon_fetches_controller.rb +2 -12
  32. data/app/controllers/source_monitor/source_fetches_controller.rb +1 -6
  33. data/app/controllers/source_monitor/source_health_checks_controller.rb +9 -16
  34. data/app/controllers/source_monitor/source_health_resets_controller.rb +1 -6
  35. data/app/controllers/source_monitor/source_retries_controller.rb +1 -6
  36. data/app/controllers/source_monitor/source_scrape_tests_controller.rb +2 -4
  37. data/app/controllers/source_monitor/source_turbo_responses.rb +1 -3
  38. data/app/controllers/source_monitor/sources_controller.rb +15 -20
  39. data/app/helpers/source_monitor/application_helper.rb +15 -31
  40. data/app/helpers/source_monitor/health_badge_helper.rb +8 -0
  41. data/app/jobs/source_monitor/download_content_images_job.rb +1 -59
  42. data/app/jobs/source_monitor/favicon_fetch_job.rb +1 -58
  43. data/app/jobs/source_monitor/fetch_feed_job.rb +2 -52
  44. data/app/jobs/source_monitor/import_opml_job.rb +6 -145
  45. data/app/jobs/source_monitor/import_session_health_check_job.rb +15 -76
  46. data/app/jobs/source_monitor/item_cleanup_job.rb +5 -0
  47. data/app/jobs/source_monitor/log_cleanup_job.rb +13 -2
  48. data/app/jobs/source_monitor/schedule_fetches_job.rb +8 -0
  49. data/app/jobs/source_monitor/scrape_item_job.rb +6 -52
  50. data/app/jobs/source_monitor/source_health_check_job.rb +1 -72
  51. data/app/models/concerns/source_monitor/loggable.rb +12 -0
  52. data/app/models/source_monitor/fetch_log.rb +0 -8
  53. data/app/models/source_monitor/health_check_log.rb +0 -8
  54. data/app/models/source_monitor/import_history.rb +14 -0
  55. data/app/models/source_monitor/import_session.rb +2 -0
  56. data/app/models/source_monitor/item.rb +15 -0
  57. data/app/models/source_monitor/item_content.rb +4 -3
  58. data/app/models/source_monitor/scrape_log.rb +4 -6
  59. data/app/models/source_monitor/source.rb +28 -19
  60. data/app/presenters/source_monitor/base_presenter.rb +19 -0
  61. data/app/presenters/source_monitor/source_details_presenter.rb +61 -0
  62. data/app/presenters/source_monitor/sources_filter_presenter.rb +61 -0
  63. data/app/views/source_monitor/dashboard/_recent_activity.html.erb +3 -3
  64. data/app/views/source_monitor/dashboard/_stat_card.html.erb +2 -1
  65. data/app/views/source_monitor/dashboard/_stats.html.erb +5 -7
  66. data/app/views/source_monitor/items/_details.html.erb +11 -14
  67. data/app/views/source_monitor/items/index.html.erb +10 -35
  68. data/app/views/source_monitor/logs/index.html.erb +20 -41
  69. data/app/views/source_monitor/shared/_form_errors.html.erb +14 -0
  70. data/app/views/source_monitor/source_scrape_tests/_result.html.erb +1 -29
  71. data/app/views/source_monitor/source_scrape_tests/_result_content.html.erb +33 -0
  72. data/app/views/source_monitor/source_scrape_tests/show.html.erb +1 -29
  73. data/app/views/source_monitor/sources/_bulk_scrape_enable_modal.html.erb +2 -2
  74. data/app/views/source_monitor/sources/_bulk_scrape_modal.html.erb +7 -5
  75. data/app/views/source_monitor/sources/_details.html.erb +24 -52
  76. data/app/views/source_monitor/sources/_health_status_badge.html.erb +4 -6
  77. data/app/views/source_monitor/sources/_row.html.erb +7 -18
  78. data/app/views/source_monitor/sources/edit.html.erb +1 -10
  79. data/app/views/source_monitor/sources/index.html.erb +26 -46
  80. data/app/views/source_monitor/sources/new.html.erb +1 -10
  81. data/config/routes.rb +1 -1
  82. data/db/migrate/20260313120000_add_composite_indexes_to_log_tables.rb +14 -0
  83. data/db/migrate/20260314120000_align_health_status_default.rb +11 -0
  84. data/lib/source_monitor/analytics/sources_index_metrics.rb +15 -0
  85. data/lib/source_monitor/dashboard/queries/recent_activity_query.rb +10 -4
  86. data/lib/source_monitor/dashboard/turbo_broadcaster.rb +21 -5
  87. data/lib/source_monitor/favicons/fetcher.rb +86 -0
  88. data/lib/source_monitor/fetching/cloudflare_bypass.rb +14 -5
  89. data/lib/source_monitor/fetching/completion/event_publisher.rb +12 -0
  90. data/lib/source_monitor/fetching/completion/follow_up_handler.rb +15 -2
  91. data/lib/source_monitor/fetching/completion/retention_handler.rb +11 -3
  92. data/lib/source_monitor/fetching/feed_fetcher.rb +2 -21
  93. data/lib/source_monitor/fetching/fetch_runner.rb +12 -3
  94. data/lib/source_monitor/fetching/retry_orchestrator.rb +102 -0
  95. data/lib/source_monitor/fetching/stalled_fetch_reconciler.rb +9 -0
  96. data/lib/source_monitor/health/source_health_check_orchestrator.rb +95 -0
  97. data/lib/source_monitor/health.rb +1 -0
  98. data/lib/source_monitor/images/downloader.rb +6 -7
  99. data/lib/source_monitor/images/processor.rb +98 -0
  100. data/lib/source_monitor/import_sessions/health_check_updater.rb +95 -0
  101. data/lib/source_monitor/import_sessions/opml_importer.rb +163 -0
  102. data/lib/source_monitor/items/item_creator.rb +0 -21
  103. data/lib/source_monitor/logs/query.rb +20 -0
  104. data/lib/source_monitor/queries/scrape_candidates_query.rb +30 -0
  105. data/lib/source_monitor/queries.rb +7 -0
  106. data/lib/source_monitor/scheduler.rb +5 -0
  107. data/lib/source_monitor/scraping/bulk_result_presenter.rb +11 -8
  108. data/lib/source_monitor/scraping/runner.rb +52 -0
  109. data/lib/source_monitor/scraping/scheduler.rb +5 -0
  110. data/lib/source_monitor/scraping/state.rb +4 -2
  111. data/lib/source_monitor/security/parameter_sanitizer.rb +7 -0
  112. data/lib/source_monitor/version.rb +1 -1
  113. data/lib/source_monitor.rb +7 -0
  114. data/source_monitor.gemspec +1 -0
  115. metadata +47 -1
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SourceMonitor
4
+ module Scraping
5
+ # Orchestrates a single item scrape: pre-flight checks (scraping enabled?),
6
+ # state management (mark_processing!, mark_failed!, clear_inflight!),
7
+ # and delegation to ItemScraper. Extracted from ScrapeItemJob so scraping
8
+ # logic can be invoked synchronously.
9
+ class Runner
10
+ def initialize(item)
11
+ @item = item
12
+ @source = item.source
13
+ end
14
+
15
+ def call
16
+ unless source&.scraping_enabled?
17
+ log("runner:skipped_scraping_disabled")
18
+ State.clear_inflight!(item)
19
+ return
20
+ end
21
+
22
+ State.mark_processing!(item)
23
+ SourceMonitor::Scraping::ItemScraper.new(item: item, source: source).call
24
+ log("runner:completed", status: item.scrape_status)
25
+ rescue StandardError => error
26
+ log("runner:error", error: error.message)
27
+ State.mark_failed!(item)
28
+ raise
29
+ ensure
30
+ State.clear_inflight!(item) if item
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :item, :source
36
+
37
+ def log(stage, **extra)
38
+ return unless defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
39
+
40
+ payload = {
41
+ stage: "SourceMonitor::Scraping::Runner##{stage}",
42
+ item_id: item&.id,
43
+ source_id: source&.id
44
+ }.merge(extra.compact)
45
+ level = stage.to_s.include?("error") ? :error : :info
46
+ Rails.logger.public_send(level, "[SourceMonitor::Scraping::Runner] #{payload.to_json}")
47
+ rescue StandardError
48
+ nil
49
+ end
50
+ end
51
+ end
52
+ end
@@ -24,6 +24,11 @@ module SourceMonitor
24
24
  result = SourceMonitor::Scraping::Enqueuer.enqueue(item: item, source: item.source, reason: :auto)
25
25
  result.enqueued? ? 1 : 0
26
26
  end
27
+ rescue StandardError => error
28
+ Rails.logger.warn(
29
+ "[SourceMonitor::Scraping::Scheduler] Scheduler run failed: #{error.class} - #{error.message}"
30
+ ) if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
31
+ 0
27
32
  end
28
33
 
29
34
  private
@@ -71,8 +71,10 @@ module SourceMonitor
71
71
 
72
72
  def broadcast_item(item)
73
73
  SourceMonitor::Realtime.broadcast_item(item)
74
- rescue StandardError
75
- nil
74
+ rescue StandardError => e
75
+ if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
76
+ Rails.logger.warn("[SourceMonitor::Scraping::State] Broadcast failed: #{e.class}: #{e.message}")
77
+ end
76
78
  end
77
79
  end
78
80
  end
@@ -7,6 +7,13 @@ module SourceMonitor
7
7
  module ParameterSanitizer
8
8
  module_function
9
9
 
10
+ def safe_redirect_path(raw_value)
11
+ return if raw_value.blank?
12
+
13
+ sanitized = sanitize(raw_value.to_s)
14
+ sanitized.start_with?("/") ? sanitized : nil
15
+ end
16
+
10
17
  def sanitize(value)
11
18
  case value
12
19
  when ActionController::Parameters
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SourceMonitor
4
- VERSION = "0.11.1"
4
+ VERSION = "0.12.0"
5
5
  end
@@ -50,6 +50,7 @@ require "source_monitor/feedjira_extensions"
50
50
 
51
51
  module SourceMonitor
52
52
  autoload :HTTP, "source_monitor/http"
53
+ autoload :Queries, "source_monitor/queries"
53
54
  autoload :Scheduler, "source_monitor/scheduler"
54
55
  autoload :Assets, "source_monitor/assets"
55
56
 
@@ -79,6 +80,7 @@ module SourceMonitor
79
80
  autoload :UnexpectedResponseError, "source_monitor/fetching/fetch_error"
80
81
  autoload :FeedFetcher, "source_monitor/fetching/feed_fetcher"
81
82
  autoload :FetchRunner, "source_monitor/fetching/fetch_runner"
83
+ autoload :RetryOrchestrator, "source_monitor/fetching/retry_orchestrator"
82
84
  autoload :RetryPolicy, "source_monitor/fetching/retry_policy"
83
85
  autoload :StalledFetchReconciler, "source_monitor/fetching/stalled_fetch_reconciler"
84
86
  autoload :AdvisoryLock, "source_monitor/fetching/advisory_lock"
@@ -88,16 +90,20 @@ module SourceMonitor
88
90
  module ImportSessions
89
91
  autoload :EntryNormalizer, "source_monitor/import_sessions/entry_normalizer"
90
92
  autoload :HealthCheckBroadcaster, "source_monitor/import_sessions/health_check_broadcaster"
93
+ autoload :HealthCheckUpdater, "source_monitor/import_sessions/health_check_updater"
94
+ autoload :OPMLImporter, "source_monitor/import_sessions/opml_importer"
91
95
  end
92
96
 
93
97
  module Favicons
94
98
  autoload :Discoverer, "source_monitor/favicons/discoverer"
99
+ autoload :Fetcher, "source_monitor/favicons/fetcher"
95
100
  autoload :SvgConverter, "source_monitor/favicons/svg_converter"
96
101
  end
97
102
 
98
103
  module Images
99
104
  autoload :ContentRewriter, "source_monitor/images/content_rewriter"
100
105
  autoload :Downloader, "source_monitor/images/downloader"
106
+ autoload :Processor, "source_monitor/images/processor"
101
107
  end
102
108
 
103
109
  module Items
@@ -152,6 +158,7 @@ module SourceMonitor
152
158
  autoload :Enqueuer, "source_monitor/scraping/enqueuer"
153
159
  autoload :BulkSourceScraper, "source_monitor/scraping/bulk_source_scraper"
154
160
  autoload :BulkResultPresenter, "source_monitor/scraping/bulk_result_presenter"
161
+ autoload :Runner, "source_monitor/scraping/runner"
155
162
  autoload :State, "source_monitor/scraping/state"
156
163
  autoload :Scheduler, "source_monitor/scraping/scheduler"
157
164
  autoload :ItemScraper, "source_monitor/scraping/item_scraper"
@@ -46,4 +46,5 @@ Gem::Specification.new do |spec|
46
46
  spec.add_dependency "solid_queue", ">= 0.3", "< 3.0"
47
47
  spec.add_dependency "solid_cable", ">= 3.0", "< 4.0"
48
48
  spec.add_dependency "ransack", "~> 4.2"
49
+ spec.add_dependency "view_component", ">= 3.0", "< 4.0"
49
50
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: source_monitor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.1
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dchuk
@@ -229,6 +229,26 @@ dependencies:
229
229
  - - "~>"
230
230
  - !ruby/object:Gem::Version
231
231
  version: '4.2'
232
+ - !ruby/object:Gem::Dependency
233
+ name: view_component
234
+ requirement: !ruby/object:Gem::Requirement
235
+ requirements:
236
+ - - ">="
237
+ - !ruby/object:Gem::Version
238
+ version: '3.0'
239
+ - - "<"
240
+ - !ruby/object:Gem::Version
241
+ version: '4.0'
242
+ type: :runtime
243
+ prerelease: false
244
+ version_requirements: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ version: '3.0'
249
+ - - "<"
250
+ - !ruby/object:Gem::Version
251
+ version: '4.0'
232
252
  description: SourceMonitor is a mountable Rails 8 engine that ingests RSS, Atom, and
233
253
  JSON feeds, scrapes full article content, and surfaces Solid Queue powered dashboards
234
254
  for monitoring and remediation.
@@ -259,6 +279,7 @@ files:
259
279
  - ".claude/agents/rails-tdd.md"
260
280
  - ".claude/agents/rails-test.md"
261
281
  - ".claude/agents/rails-view-component.md"
282
+ - ".claude/commands/rails-audit.md"
262
283
  - ".claude/commands/release.md"
263
284
  - ".claude/hooks/block-secrets.sh"
264
285
  - ".claude/settings.json"
@@ -350,6 +371,7 @@ files:
350
371
  - Gemfile
351
372
  - Gemfile.lock
352
373
  - MIT-LICENSE
374
+ - RAILS_AUDIT.md
353
375
  - README.md
354
376
  - Rakefile
355
377
  - VERSION
@@ -363,6 +385,7 @@ files:
363
385
  - app/assets/javascripts/source_monitor/controllers/async_submit_controller.js
364
386
  - app/assets/javascripts/source_monitor/controllers/confirm_navigation_controller.js
365
387
  - app/assets/javascripts/source_monitor/controllers/dropdown_controller.js
388
+ - app/assets/javascripts/source_monitor/controllers/filter_submit_controller.js
366
389
  - app/assets/javascripts/source_monitor/controllers/modal_controller.js
367
390
  - app/assets/javascripts/source_monitor/controllers/notification_container_controller.js
368
391
  - app/assets/javascripts/source_monitor/controllers/notification_controller.js
@@ -370,8 +393,14 @@ files:
370
393
  - app/assets/javascripts/source_monitor/turbo_actions.js
371
394
  - app/assets/stylesheets/source_monitor/application.tailwind.css
372
395
  - app/assets/svgs/source_monitor/.keep
396
+ - app/components/source_monitor/application_component.rb
397
+ - app/components/source_monitor/filter_dropdown_component.rb
398
+ - app/components/source_monitor/icon_component.rb
399
+ - app/components/source_monitor/status_badge_component.html.erb
400
+ - app/components/source_monitor/status_badge_component.rb
373
401
  - app/controllers/concerns/.keep
374
402
  - app/controllers/concerns/source_monitor/sanitizes_search_params.rb
403
+ - app/controllers/concerns/source_monitor/set_source.rb
375
404
  - app/controllers/source_monitor/application_controller.rb
376
405
  - app/controllers/source_monitor/bulk_scrape_enablements_controller.rb
377
406
  - app/controllers/source_monitor/dashboard_controller.rb
@@ -383,6 +412,7 @@ files:
383
412
  - app/controllers/source_monitor/import_sessions/health_check_management.rb
384
413
  - app/controllers/source_monitor/import_sessions/opml_parser.rb
385
414
  - app/controllers/source_monitor/import_sessions_controller.rb
415
+ - app/controllers/source_monitor/item_scrapes_controller.rb
386
416
  - app/controllers/source_monitor/items_controller.rb
387
417
  - app/controllers/source_monitor/logs_controller.rb
388
418
  - app/controllers/source_monitor/scrape_logs_controller.rb
@@ -422,6 +452,9 @@ files:
422
452
  - app/models/source_monitor/log_entry.rb
423
453
  - app/models/source_monitor/scrape_log.rb
424
454
  - app/models/source_monitor/source.rb
455
+ - app/presenters/source_monitor/base_presenter.rb
456
+ - app/presenters/source_monitor/source_details_presenter.rb
457
+ - app/presenters/source_monitor/sources_filter_presenter.rb
425
458
  - app/views/layouts/source_monitor/application.html.erb
426
459
  - app/views/source_monitor/dashboard/_fetch_schedule.html.erb
427
460
  - app/views/source_monitor/dashboard/_job_metrics.html.erb
@@ -449,9 +482,11 @@ files:
449
482
  - app/views/source_monitor/items/show.html.erb
450
483
  - app/views/source_monitor/logs/index.html.erb
451
484
  - app/views/source_monitor/scrape_logs/show.html.erb
485
+ - app/views/source_monitor/shared/_form_errors.html.erb
452
486
  - app/views/source_monitor/shared/_pagination.html.erb
453
487
  - app/views/source_monitor/shared/_toast.html.erb
454
488
  - app/views/source_monitor/source_scrape_tests/_result.html.erb
489
+ - app/views/source_monitor/source_scrape_tests/_result_content.html.erb
455
490
  - app/views/source_monitor/source_scrape_tests/show.html.erb
456
491
  - app/views/source_monitor/sources/_bulk_scrape_enable_modal.html.erb
457
492
  - app/views/source_monitor/sources/_bulk_scrape_form.html.erb
@@ -505,6 +540,8 @@ files:
505
540
  - db/migrate/20260306233004_add_error_category_to_fetch_logs.rb
506
541
  - db/migrate/20260307120000_add_consecutive_fetch_failures_to_sources.rb
507
542
  - db/migrate/20260312120000_simplify_health_status_values.rb
543
+ - db/migrate/20260313120000_add_composite_indexes_to_log_tables.rb
544
+ - db/migrate/20260314120000_align_health_status_default.rb
508
545
  - docs/configuration.md
509
546
  - docs/deployment.md
510
547
  - docs/gh-cli-workflow.md
@@ -550,6 +587,7 @@ files:
550
587
  - lib/source_monitor/engine.rb
551
588
  - lib/source_monitor/events.rb
552
589
  - lib/source_monitor/favicons/discoverer.rb
590
+ - lib/source_monitor/favicons/fetcher.rb
553
591
  - lib/source_monitor/favicons/svg_converter.rb
554
592
  - lib/source_monitor/feedjira_extensions.rb
555
593
  - lib/source_monitor/fetching/advisory_lock.rb
@@ -563,19 +601,24 @@ files:
563
601
  - lib/source_monitor/fetching/feed_fetcher/source_updater.rb
564
602
  - lib/source_monitor/fetching/fetch_error.rb
565
603
  - lib/source_monitor/fetching/fetch_runner.rb
604
+ - lib/source_monitor/fetching/retry_orchestrator.rb
566
605
  - lib/source_monitor/fetching/retry_policy.rb
567
606
  - lib/source_monitor/fetching/stalled_fetch_reconciler.rb
568
607
  - lib/source_monitor/health.rb
569
608
  - lib/source_monitor/health/import_source_health_check.rb
570
609
  - lib/source_monitor/health/source_health_check.rb
610
+ - lib/source_monitor/health/source_health_check_orchestrator.rb
571
611
  - lib/source_monitor/health/source_health_monitor.rb
572
612
  - lib/source_monitor/health/source_health_reset.rb
573
613
  - lib/source_monitor/http.rb
574
614
  - lib/source_monitor/http/aia_resolver.rb
575
615
  - lib/source_monitor/images/content_rewriter.rb
576
616
  - lib/source_monitor/images/downloader.rb
617
+ - lib/source_monitor/images/processor.rb
577
618
  - lib/source_monitor/import_sessions/entry_normalizer.rb
578
619
  - lib/source_monitor/import_sessions/health_check_broadcaster.rb
620
+ - lib/source_monitor/import_sessions/health_check_updater.rb
621
+ - lib/source_monitor/import_sessions/opml_importer.rb
579
622
  - lib/source_monitor/instrumentation.rb
580
623
  - lib/source_monitor/items/item_creator.rb
581
624
  - lib/source_monitor/items/item_creator/content_extractor.rb
@@ -598,6 +641,8 @@ files:
598
641
  - lib/source_monitor/models/sanitizable.rb
599
642
  - lib/source_monitor/models/url_normalizable.rb
600
643
  - lib/source_monitor/pagination/paginator.rb
644
+ - lib/source_monitor/queries.rb
645
+ - lib/source_monitor/queries/scrape_candidates_query.rb
601
646
  - lib/source_monitor/realtime.rb
602
647
  - lib/source_monitor/realtime/adapter.rb
603
648
  - lib/source_monitor/realtime/broadcaster.rb
@@ -614,6 +659,7 @@ files:
614
659
  - lib/source_monitor/scraping/item_scraper.rb
615
660
  - lib/source_monitor/scraping/item_scraper/adapter_resolver.rb
616
661
  - lib/source_monitor/scraping/item_scraper/persistence.rb
662
+ - lib/source_monitor/scraping/runner.rb
617
663
  - lib/source_monitor/scraping/scheduler.rb
618
664
  - lib/source_monitor/scraping/state.rb
619
665
  - lib/source_monitor/security/authentication.rb