source_monitor 0.2.1 → 0.3.1
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.
- checksums.yaml +4 -4
- data/.claude/agents/rails-concern.md +464 -0
- data/.claude/agents/rails-controller.md +424 -0
- data/.claude/agents/rails-hotwire.md +446 -0
- data/.claude/agents/rails-implement.md +374 -0
- data/.claude/agents/rails-job.md +334 -0
- data/.claude/agents/rails-lint.md +294 -0
- data/.claude/agents/rails-mailer.md +371 -0
- data/.claude/agents/rails-migration.md +449 -0
- data/.claude/agents/rails-model.md +420 -0
- data/.claude/agents/rails-policy.md +443 -0
- data/.claude/agents/rails-presenter.md +427 -0
- data/.claude/agents/rails-query.md +412 -0
- data/.claude/agents/rails-review.md +490 -0
- data/.claude/agents/rails-service.md +458 -0
- data/.claude/agents/rails-state-records.md +465 -0
- data/.claude/agents/rails-tdd.md +314 -0
- data/.claude/agents/rails-test.md +441 -0
- data/.claude/agents/rails-view-component.md +418 -0
- data/.claude/hooks/block-secrets.sh +52 -0
- data/.claude/settings.json +85 -0
- data/.claude/skills/action-cable-patterns/SKILL.md +296 -0
- data/.claude/skills/action-mailer-patterns/SKILL.md +295 -0
- data/.claude/skills/active-storage-setup/SKILL.md +311 -0
- data/.claude/skills/api-versioning/SKILL.md +294 -0
- data/.claude/skills/authentication-flow/SKILL.md +335 -0
- data/.claude/skills/authentication-flow/reference/current.md +248 -0
- data/.claude/skills/authentication-flow/reference/passwordless.md +253 -0
- data/.claude/skills/authentication-flow/reference/sessions.md +201 -0
- data/.claude/skills/authorization-pundit/SKILL.md +462 -0
- data/.claude/skills/caching-strategies/SKILL.md +350 -0
- data/.claude/skills/database-migrations/SKILL.md +354 -0
- data/.claude/skills/form-object-patterns/SKILL.md +399 -0
- data/.claude/skills/hotwire-patterns/SKILL.md +247 -0
- data/.claude/skills/hotwire-patterns/reference/stimulus.md +307 -0
- data/.claude/skills/hotwire-patterns/reference/tailwind-integration.md +112 -0
- data/.claude/skills/hotwire-patterns/reference/turbo-frames.md +158 -0
- data/.claude/skills/hotwire-patterns/reference/turbo-streams.md +218 -0
- data/.claude/skills/i18n-patterns/SKILL.md +320 -0
- data/.claude/skills/install/SKILL.md +367 -0
- data/.claude/skills/performance-optimization/SKILL.md +311 -0
- data/.claude/skills/rails-architecture/SKILL.md +259 -0
- data/.claude/skills/rails-architecture/reference/error-handling.md +333 -0
- data/.claude/skills/rails-architecture/reference/event-tracking.md +142 -0
- data/.claude/skills/rails-architecture/reference/layer-interactions.md +417 -0
- data/.claude/skills/rails-architecture/reference/multi-tenancy.md +152 -0
- data/.claude/skills/rails-architecture/reference/query-patterns.md +342 -0
- data/.claude/skills/rails-architecture/reference/service-patterns.md +286 -0
- data/.claude/skills/rails-architecture/reference/state-records.md +250 -0
- data/.claude/skills/rails-architecture/reference/testing-strategy.md +326 -0
- data/.claude/skills/rails-concern/SKILL.md +399 -0
- data/.claude/skills/rails-controller/SKILL.md +336 -0
- data/.claude/skills/rails-model-generator/SKILL.md +321 -0
- data/.claude/skills/rails-model-generator/reference/validations.md +298 -0
- data/.claude/skills/rails-presenter/SKILL.md +274 -0
- data/.claude/skills/rails-query-object/SKILL.md +289 -0
- data/.claude/skills/rails-service-object/SKILL.md +349 -0
- data/.claude/skills/sm-architecture/SKILL.md +233 -0
- data/.claude/skills/sm-architecture/reference/extraction-patterns.md +192 -0
- data/.claude/skills/sm-architecture/reference/module-map.md +194 -0
- data/.claude/skills/sm-configuration-setting/SKILL.md +264 -0
- data/.claude/skills/sm-configuration-setting/reference/settings-catalog.md +248 -0
- data/.claude/skills/sm-configuration-setting/reference/settings-pattern.md +297 -0
- data/.claude/skills/sm-configure/SKILL.md +153 -0
- data/.claude/skills/sm-configure/reference/configuration-reference.md +321 -0
- data/.claude/skills/sm-dashboard-widget/SKILL.md +344 -0
- data/.claude/skills/sm-dashboard-widget/reference/dashboard-patterns.md +304 -0
- data/.claude/skills/sm-domain-model/SKILL.md +188 -0
- data/.claude/skills/sm-domain-model/reference/model-graph.md +114 -0
- data/.claude/skills/sm-domain-model/reference/table-structure.md +348 -0
- data/.claude/skills/sm-engine-migration/SKILL.md +395 -0
- data/.claude/skills/sm-engine-migration/reference/migration-conventions.md +255 -0
- data/.claude/skills/sm-engine-test/SKILL.md +302 -0
- data/.claude/skills/sm-engine-test/reference/test-helpers.md +259 -0
- data/.claude/skills/sm-engine-test/reference/test-patterns.md +411 -0
- data/.claude/skills/sm-event-handler/SKILL.md +265 -0
- data/.claude/skills/sm-event-handler/reference/events-api.md +229 -0
- data/.claude/skills/sm-health-rule/SKILL.md +327 -0
- data/.claude/skills/sm-health-rule/reference/health-system.md +269 -0
- data/.claude/skills/sm-host-setup/SKILL.md +223 -0
- data/.claude/skills/sm-host-setup/reference/initializer-template.md +195 -0
- data/.claude/skills/sm-host-setup/reference/setup-checklist.md +134 -0
- data/.claude/skills/sm-job/SKILL.md +263 -0
- data/.claude/skills/sm-job/reference/job-conventions.md +245 -0
- data/.claude/skills/sm-model-extension/SKILL.md +287 -0
- data/.claude/skills/sm-model-extension/reference/extension-api.md +317 -0
- data/.claude/skills/sm-pipeline-stage/SKILL.md +254 -0
- data/.claude/skills/sm-pipeline-stage/reference/completion-handlers.md +152 -0
- data/.claude/skills/sm-pipeline-stage/reference/entry-processing.md +191 -0
- data/.claude/skills/sm-pipeline-stage/reference/feed-fetcher-architecture.md +198 -0
- data/.claude/skills/sm-scraper-adapter/SKILL.md +284 -0
- data/.claude/skills/sm-scraper-adapter/reference/adapter-contract.md +167 -0
- data/.claude/skills/sm-scraper-adapter/reference/example-adapter.md +274 -0
- data/.claude/skills/solid-queue-setup/SKILL.md +307 -0
- data/.claude/skills/tdd-cycle/SKILL.md +359 -0
- data/.claude/skills/viewcomponent-patterns/SKILL.md +333 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/.vbw-planning/.notification-log.jsonl +246 -0
- data/.vbw-planning/.session-log.jsonl +992 -0
- data/.vbw-planning/PROJECT.md +51 -0
- data/.vbw-planning/REQUIREMENTS.md +50 -0
- data/.vbw-planning/SHIPPED.md +28 -0
- data/.vbw-planning/codebase/ARCHITECTURE.md +147 -0
- data/.vbw-planning/codebase/CONCERNS.md +99 -0
- data/.vbw-planning/codebase/CONVENTIONS.md +97 -0
- data/.vbw-planning/codebase/DEPENDENCIES.md +100 -0
- data/.vbw-planning/codebase/INDEX.md +86 -0
- data/.vbw-planning/codebase/META.md +42 -0
- data/.vbw-planning/codebase/PATTERNS.md +262 -0
- data/.vbw-planning/codebase/STACK.md +101 -0
- data/.vbw-planning/codebase/STRUCTURE.md +324 -0
- data/.vbw-planning/codebase/TESTING.md +154 -0
- data/.vbw-planning/config.json +12 -0
- data/.vbw-planning/discovery.json +24 -0
- data/.vbw-planning/milestones/default/ROADMAP.md +115 -0
- data/.vbw-planning/milestones/default/STATE.md +83 -0
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-01-SUMMARY.md +56 -0
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-01.md +187 -0
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-02-SUMMARY.md +64 -0
- data/.vbw-planning/milestones/default/phases/01-coverage-analysis-quick-wins/PLAN-02.md +137 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-01-SUMMARY.md +67 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-01.md +142 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-02-SUMMARY.md +64 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-02.md +138 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-03-SUMMARY.md +85 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-03.md +147 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-04-SUMMARY.md +63 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-04.md +129 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-05-SUMMARY.md +74 -0
- data/.vbw-planning/milestones/default/phases/02-critical-path-test-coverage/PLAN-05.md +154 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/03-VERIFICATION-wave1.md +303 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/03-VERIFICATION.md +510 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-01-SUMMARY.md +61 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-01.md +161 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-02-SUMMARY.md +66 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-02.md +132 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-03-SUMMARY.md +59 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-03.md +171 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-04-SUMMARY.md +56 -0
- data/.vbw-planning/milestones/default/phases/03-large-file-refactoring/PLAN-04.md +152 -0
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/04-CONTEXT.md +33 -0
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-01-SUMMARY.md +42 -0
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-01.md +119 -0
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-02-SUMMARY.md +52 -0
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-02.md +195 -0
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-03-SUMMARY.md +79 -0
- data/.vbw-planning/milestones/default/phases/04-code-quality-conventions-cleanup/PLAN-03.md +130 -0
- data/CHANGELOG.md +37 -0
- data/CLAUDE.md +222 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +132 -120
- data/Rakefile +2 -0
- data/app/controllers/source_monitor/application_controller.rb +2 -0
- data/app/controllers/source_monitor/health_controller.rb +2 -0
- data/app/controllers/source_monitor/import_sessions/bulk_configuration.rb +106 -0
- data/app/controllers/source_monitor/import_sessions/entry_annotation.rb +187 -0
- data/app/controllers/source_monitor/import_sessions/health_check_management.rb +112 -0
- data/app/controllers/source_monitor/import_sessions/opml_parser.rb +130 -0
- data/app/controllers/source_monitor/import_sessions_controller.rb +6 -507
- data/app/controllers/source_monitor/items_controller.rb +2 -0
- data/app/controllers/source_monitor/sources_controller.rb +0 -14
- data/app/helpers/source_monitor/application_helper.rb +4 -112
- data/app/helpers/source_monitor/health_badge_helper.rb +69 -0
- data/app/helpers/source_monitor/table_sort_helper.rb +53 -0
- data/app/jobs/source_monitor/application_job.rb +2 -0
- data/app/models/source_monitor/application_record.rb +2 -0
- data/app/models/source_monitor/log_entry.rb +0 -2
- data/config/coverage_baseline.json +217 -1862
- data/config/routes.rb +2 -0
- data/db/migrate/20251009103000_add_feed_content_readability_to_sources.rb +2 -0
- data/db/migrate/20251014171659_add_performance_indexes.rb +2 -0
- data/db/migrate/20251014172525_add_fetch_status_check_constraint.rb +2 -0
- data/db/migrate/20251108120116_refresh_fetch_status_constraint.rb +2 -0
- data/db/migrate/20260210204022_add_composite_index_to_log_entries.rb +17 -0
- data/lib/source_monitor/assets/bundler.rb +2 -0
- data/lib/source_monitor/assets.rb +2 -0
- data/lib/source_monitor/configuration/authentication_settings.rb +62 -0
- data/lib/source_monitor/configuration/events.rb +60 -0
- data/lib/source_monitor/configuration/fetching_settings.rb +27 -0
- data/lib/source_monitor/configuration/health_settings.rb +27 -0
- data/lib/source_monitor/configuration/http_settings.rb +43 -0
- data/lib/source_monitor/configuration/model_definition.rb +108 -0
- data/lib/source_monitor/configuration/models.rb +36 -0
- data/lib/source_monitor/configuration/realtime_settings.rb +95 -0
- data/lib/source_monitor/configuration/retention_settings.rb +45 -0
- data/lib/source_monitor/configuration/scraper_registry.rb +67 -0
- data/lib/source_monitor/configuration/scraping_settings.rb +39 -0
- data/lib/source_monitor/configuration/validation_definition.rb +32 -0
- data/lib/source_monitor/configuration.rb +12 -579
- data/lib/source_monitor/dashboard/queries/recent_activity_query.rb +138 -0
- data/lib/source_monitor/dashboard/queries/stats_query.rb +71 -0
- data/lib/source_monitor/dashboard/queries.rb +2 -195
- data/lib/source_monitor/engine.rb +2 -0
- data/lib/source_monitor/fetching/feed_fetcher/adaptive_interval.rb +141 -0
- data/lib/source_monitor/fetching/feed_fetcher/entry_processor.rb +89 -0
- data/lib/source_monitor/fetching/feed_fetcher/source_updater.rb +200 -0
- data/lib/source_monitor/fetching/feed_fetcher.rb +37 -379
- data/lib/source_monitor/items/item_creator/content_extractor.rb +113 -0
- data/lib/source_monitor/items/item_creator/entry_parser/media_extraction.rb +96 -0
- data/lib/source_monitor/items/item_creator/entry_parser.rb +294 -0
- data/lib/source_monitor/items/item_creator.rb +28 -455
- data/lib/source_monitor/setup/bundle_installer.rb +2 -0
- data/lib/source_monitor/setup/cli.rb +2 -0
- data/lib/source_monitor/setup/dependency_checker.rb +2 -0
- data/lib/source_monitor/setup/detectors.rb +2 -0
- data/lib/source_monitor/setup/gemfile_editor.rb +2 -0
- data/lib/source_monitor/setup/initializer_patcher.rb +2 -0
- data/lib/source_monitor/setup/install_generator.rb +2 -0
- data/lib/source_monitor/setup/migration_installer.rb +2 -0
- data/lib/source_monitor/setup/node_installer.rb +2 -0
- data/lib/source_monitor/setup/prompter.rb +2 -0
- data/lib/source_monitor/setup/requirements.rb +2 -0
- data/lib/source_monitor/setup/shell_runner.rb +2 -0
- data/lib/source_monitor/setup/verification/action_cable_verifier.rb +2 -0
- data/lib/source_monitor/setup/verification/printer.rb +2 -0
- data/lib/source_monitor/setup/verification/result.rb +2 -0
- data/lib/source_monitor/setup/verification/runner.rb +2 -0
- data/lib/source_monitor/setup/verification/solid_queue_verifier.rb +2 -0
- data/lib/source_monitor/setup/verification/telemetry_logger.rb +2 -0
- data/lib/source_monitor/setup/workflow.rb +19 -2
- data/lib/source_monitor/version.rb +3 -1
- data/lib/source_monitor.rb +140 -58
- data/lib/tasks/source_monitor_assets.rake +2 -0
- data/lib/tasks/source_monitor_setup.rake +60 -0
- data/lib/tasks/source_monitor_tasks.rake +2 -0
- data/source_monitor.gemspec +4 -1
- metadata +177 -4
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# Configuration Settings Catalog
|
|
2
|
+
|
|
3
|
+
All configuration sections with their attributes, defaults, and types.
|
|
4
|
+
|
|
5
|
+
## Top-Level Attributes
|
|
6
|
+
|
|
7
|
+
**File:** `lib/source_monitor/configuration.rb`
|
|
8
|
+
|
|
9
|
+
| Attribute | Type | Default | Description |
|
|
10
|
+
|-----------|------|---------|-------------|
|
|
11
|
+
| `queue_namespace` | String | `"source_monitor"` | Namespace prefix for queue names |
|
|
12
|
+
| `fetch_queue_name` | String | `"source_monitor_fetch"` | Queue name for fetch jobs |
|
|
13
|
+
| `scrape_queue_name` | String | `"source_monitor_scrape"` | Queue name for scrape jobs |
|
|
14
|
+
| `fetch_queue_concurrency` | Integer | `2` | Max concurrent fetch workers |
|
|
15
|
+
| `scrape_queue_concurrency` | Integer | `2` | Max concurrent scrape workers |
|
|
16
|
+
| `recurring_command_job_class` | Class/nil | `nil` | Custom recurring job class |
|
|
17
|
+
| `job_metrics_enabled` | Boolean | `true` | Enable job metrics tracking |
|
|
18
|
+
| `mission_control_enabled` | Boolean | `false` | Enable Mission Control integration |
|
|
19
|
+
| `mission_control_dashboard_path` | String/Proc/nil | `nil` | Path or callable for Mission Control |
|
|
20
|
+
|
|
21
|
+
**Methods:**
|
|
22
|
+
- `queue_name_for(:fetch)` / `queue_name_for(:scrape)` -- Returns prefixed queue name
|
|
23
|
+
- `concurrency_for(:fetch)` / `concurrency_for(:scrape)` -- Returns concurrency limit
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## HTTPSettings
|
|
28
|
+
|
|
29
|
+
**File:** `lib/source_monitor/configuration/http_settings.rb`
|
|
30
|
+
|
|
31
|
+
| Attribute | Type | Default | Description |
|
|
32
|
+
|-----------|------|---------|-------------|
|
|
33
|
+
| `timeout` | Integer | `15` | Total request timeout (seconds) |
|
|
34
|
+
| `open_timeout` | Integer | `5` | Connection open timeout (seconds) |
|
|
35
|
+
| `max_redirects` | Integer | `5` | Max HTTP redirects to follow |
|
|
36
|
+
| `user_agent` | String | `"SourceMonitor/<version>"` | User-Agent header value |
|
|
37
|
+
| `proxy` | String/nil | `nil` | HTTP proxy URL |
|
|
38
|
+
| `headers` | Hash | `{}` | Default HTTP headers |
|
|
39
|
+
| `retry_max` | Integer | `4` | Max retry attempts |
|
|
40
|
+
| `retry_interval` | Float | `0.5` | Base retry interval (seconds) |
|
|
41
|
+
| `retry_interval_randomness` | Float | `0.5` | Retry interval randomness factor |
|
|
42
|
+
| `retry_backoff_factor` | Integer | `2` | Exponential backoff multiplier |
|
|
43
|
+
| `retry_statuses` | Array/nil | `nil` | HTTP statuses to retry on |
|
|
44
|
+
|
|
45
|
+
Has `reset!` method.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## FetchingSettings
|
|
50
|
+
|
|
51
|
+
**File:** `lib/source_monitor/configuration/fetching_settings.rb`
|
|
52
|
+
|
|
53
|
+
| Attribute | Type | Default | Description |
|
|
54
|
+
|-----------|------|---------|-------------|
|
|
55
|
+
| `min_interval_minutes` | Integer | `5` | Minimum fetch interval |
|
|
56
|
+
| `max_interval_minutes` | Integer | `1440` (24h) | Maximum fetch interval |
|
|
57
|
+
| `increase_factor` | Float | `1.25` | Multiplier when content unchanged |
|
|
58
|
+
| `decrease_factor` | Float | `0.75` | Multiplier when content changed |
|
|
59
|
+
| `failure_increase_factor` | Float | `1.5` | Multiplier on fetch failure |
|
|
60
|
+
| `jitter_percent` | Float | `0.1` | Random jitter (10%) |
|
|
61
|
+
|
|
62
|
+
Has `reset!` method. All attributes are plain `attr_accessor`.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## HealthSettings
|
|
67
|
+
|
|
68
|
+
**File:** `lib/source_monitor/configuration/health_settings.rb`
|
|
69
|
+
|
|
70
|
+
| Attribute | Type | Default | Description |
|
|
71
|
+
|-----------|------|---------|-------------|
|
|
72
|
+
| `window_size` | Integer | `20` | Rolling window of fetches for health calc |
|
|
73
|
+
| `healthy_threshold` | Float | `0.8` | Success rate above = healthy |
|
|
74
|
+
| `warning_threshold` | Float | `0.5` | Success rate above = warning |
|
|
75
|
+
| `auto_pause_threshold` | Float | `0.2` | Success rate below = auto-pause |
|
|
76
|
+
| `auto_resume_threshold` | Float | `0.6` | Success rate above = auto-resume |
|
|
77
|
+
| `auto_pause_cooldown_minutes` | Integer | `60` | Cooldown before auto-resume check |
|
|
78
|
+
|
|
79
|
+
Has `reset!` method. All attributes are plain `attr_accessor`.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## ScrapingSettings
|
|
84
|
+
|
|
85
|
+
**File:** `lib/source_monitor/configuration/scraping_settings.rb`
|
|
86
|
+
|
|
87
|
+
| Attribute | Type | Default | Description |
|
|
88
|
+
|-----------|------|---------|-------------|
|
|
89
|
+
| `max_in_flight_per_source` | Integer/nil | `25` | Max concurrent scrape jobs per source |
|
|
90
|
+
| `max_bulk_batch_size` | Integer/nil | `100` | Max items in a bulk scrape batch |
|
|
91
|
+
|
|
92
|
+
Has `reset!` method. Custom setters normalize values:
|
|
93
|
+
- `nil` -> `nil`
|
|
94
|
+
- `""` -> `nil`
|
|
95
|
+
- `0` or negative -> `nil`
|
|
96
|
+
- String -> parsed integer (if positive)
|
|
97
|
+
- Positive integer -> kept as-is
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## RetentionSettings
|
|
102
|
+
|
|
103
|
+
**File:** `lib/source_monitor/configuration/retention_settings.rb`
|
|
104
|
+
|
|
105
|
+
| Attribute | Type | Default | Description |
|
|
106
|
+
|-----------|------|---------|-------------|
|
|
107
|
+
| `items_retention_days` | Integer/nil | `nil` | Days to keep items (nil = forever) |
|
|
108
|
+
| `max_items` | Integer/nil | `nil` | Max items per source (nil = unlimited) |
|
|
109
|
+
| `strategy` | Symbol | `:destroy` | `:destroy` or `:soft_delete` |
|
|
110
|
+
|
|
111
|
+
No `reset!` method (defaults set in `initialize`). The `strategy=` setter validates against allowed values and raises `ArgumentError` for invalid input. Setting `nil` resets to `:destroy`.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## RealtimeSettings
|
|
116
|
+
|
|
117
|
+
**File:** `lib/source_monitor/configuration/realtime_settings.rb`
|
|
118
|
+
|
|
119
|
+
| Attribute | Type | Default | Description |
|
|
120
|
+
|-----------|------|---------|-------------|
|
|
121
|
+
| `adapter` | Symbol | `:solid_cable` | One of `:solid_cable`, `:redis`, `:async` |
|
|
122
|
+
| `redis_url` | String/nil | `nil` | Redis URL (for `:redis` adapter) |
|
|
123
|
+
| `solid_cable` | SolidCableOptions | (nested object) | Solid Cable options |
|
|
124
|
+
|
|
125
|
+
Has `reset!` method. The `adapter=` setter validates against `VALID_ADAPTERS`.
|
|
126
|
+
|
|
127
|
+
**SolidCableOptions:**
|
|
128
|
+
|
|
129
|
+
| Attribute | Type | Default |
|
|
130
|
+
|-----------|------|---------|
|
|
131
|
+
| `polling_interval` | String | `"0.1.seconds"` |
|
|
132
|
+
| `message_retention` | String | `"1.day"` |
|
|
133
|
+
| `autotrim` | Boolean | `true` |
|
|
134
|
+
| `silence_polling` | Boolean | `true` |
|
|
135
|
+
| `use_skip_locked` | Boolean | `true` |
|
|
136
|
+
| `trim_batch_size` | Integer/nil | `nil` |
|
|
137
|
+
| `connects_to` | Hash/nil | `nil` |
|
|
138
|
+
|
|
139
|
+
**Methods:**
|
|
140
|
+
- `action_cable_config` -- Returns hash suitable for ActionCable configuration
|
|
141
|
+
- `solid_cable=(hash)` -- Bulk-assign SolidCable options from a hash
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## AuthenticationSettings
|
|
146
|
+
|
|
147
|
+
**File:** `lib/source_monitor/configuration/authentication_settings.rb`
|
|
148
|
+
|
|
149
|
+
| Attribute | Type | Default | Description |
|
|
150
|
+
|-----------|------|---------|-------------|
|
|
151
|
+
| `authenticate_handler` | Handler/nil | `nil` | Authentication handler |
|
|
152
|
+
| `authorize_handler` | Handler/nil | `nil` | Authorization handler |
|
|
153
|
+
| `current_user_method` | Symbol/nil | `nil` | Method name for current user |
|
|
154
|
+
| `user_signed_in_method` | Symbol/nil | `nil` | Method name for signed-in check |
|
|
155
|
+
|
|
156
|
+
Has `reset!` method.
|
|
157
|
+
|
|
158
|
+
**Methods:**
|
|
159
|
+
- `authenticate_with(handler = nil, &block)` -- Register authentication handler
|
|
160
|
+
- `authorize_with(handler = nil, &block)` -- Register authorization handler
|
|
161
|
+
|
|
162
|
+
Handler types: `:symbol` (method name), `:callable` (lambda/proc/block).
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Events
|
|
167
|
+
|
|
168
|
+
**File:** `lib/source_monitor/configuration/events.rb`
|
|
169
|
+
|
|
170
|
+
| Callback Key | Description |
|
|
171
|
+
|-------------|-------------|
|
|
172
|
+
| `after_item_created` | Fires after a new item is created from a feed entry |
|
|
173
|
+
| `after_item_scraped` | Fires after an item's content is scraped |
|
|
174
|
+
| `after_fetch_completed` | Fires after a feed fetch completes (success or failure) |
|
|
175
|
+
|
|
176
|
+
**Methods:**
|
|
177
|
+
- `after_item_created(handler = nil, &block)` -- Register callback
|
|
178
|
+
- `after_item_scraped(handler = nil, &block)` -- Register callback
|
|
179
|
+
- `after_fetch_completed(handler = nil, &block)` -- Register callback
|
|
180
|
+
- `register_item_processor(processor = nil, &block)` -- Register item processor
|
|
181
|
+
- `callbacks_for(name)` -- Returns array of callbacks (dup'd)
|
|
182
|
+
- `item_processors` -- Returns array of processors (dup'd)
|
|
183
|
+
- `reset!` -- Clears all callbacks and processors
|
|
184
|
+
|
|
185
|
+
All handlers must respond to `#call`. Raises `ArgumentError` otherwise.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## ScraperRegistry
|
|
190
|
+
|
|
191
|
+
**File:** `lib/source_monitor/configuration/scraper_registry.rb`
|
|
192
|
+
|
|
193
|
+
Enumerable registry of scraper adapters.
|
|
194
|
+
|
|
195
|
+
**Methods:**
|
|
196
|
+
- `register(name, adapter)` -- Register adapter class by name
|
|
197
|
+
- `unregister(name)` -- Remove adapter
|
|
198
|
+
- `adapter_for(name)` -- Look up adapter class by name
|
|
199
|
+
- `each` -- Iterate over `{name => adapter}` pairs
|
|
200
|
+
|
|
201
|
+
Names are normalized to lowercase alphanumeric + underscores. Adapter classes must inherit from `SourceMonitor::Scrapers::Base`.
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Models
|
|
206
|
+
|
|
207
|
+
**File:** `lib/source_monitor/configuration/models.rb`
|
|
208
|
+
|
|
209
|
+
| Attribute | Type | Default | Description |
|
|
210
|
+
|-----------|------|---------|-------------|
|
|
211
|
+
| `table_name_prefix` | String | `"sourcemon_"` | Database table prefix |
|
|
212
|
+
|
|
213
|
+
**Model Keys:** `source`, `item`, `fetch_log`, `scrape_log`, `health_check_log`, `item_content`, `log_entry`
|
|
214
|
+
|
|
215
|
+
Each key returns a `ModelDefinition` instance.
|
|
216
|
+
|
|
217
|
+
**Methods:**
|
|
218
|
+
- `for(name)` -- Returns `ModelDefinition` by name (raises on unknown)
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## ModelDefinition
|
|
223
|
+
|
|
224
|
+
**File:** `lib/source_monitor/configuration/model_definition.rb`
|
|
225
|
+
|
|
226
|
+
**Methods:**
|
|
227
|
+
- `include_concern(concern = nil, &block)` -- Register a concern module
|
|
228
|
+
- `each_concern` -- Iterate over registered concerns (yields `[signature, resolved_module]`)
|
|
229
|
+
- `validate(handler = nil, **options, &block)` -- Register a custom validation
|
|
230
|
+
- `validations` -- Returns array of `ValidationDefinition` instances
|
|
231
|
+
|
|
232
|
+
Concerns can be: Module instance, String constant name, or anonymous block.
|
|
233
|
+
Validations can be: Symbol method name, String, lambda, or block.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## ValidationDefinition
|
|
238
|
+
|
|
239
|
+
**File:** `lib/source_monitor/configuration/validation_definition.rb`
|
|
240
|
+
|
|
241
|
+
| Attribute | Type | Description |
|
|
242
|
+
|-----------|------|-------------|
|
|
243
|
+
| `handler` | Symbol/Proc | The validation handler |
|
|
244
|
+
| `options` | Hash | Options hash (e.g., `{ if: :active? }`) |
|
|
245
|
+
|
|
246
|
+
**Methods:**
|
|
247
|
+
- `signature` -- Returns deduplication key
|
|
248
|
+
- `symbol?` -- Returns true if handler is a Symbol or String
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# Step-by-Step: Adding a Configuration Setting
|
|
2
|
+
|
|
3
|
+
## Scenario A: Add to Existing Section
|
|
4
|
+
|
|
5
|
+
### Example: Add `stale_threshold_hours` to FetchingSettings
|
|
6
|
+
|
|
7
|
+
**Step 1: Edit the settings file**
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
# lib/source_monitor/configuration/fetching_settings.rb
|
|
11
|
+
class FetchingSettings
|
|
12
|
+
attr_accessor :min_interval_minutes,
|
|
13
|
+
:max_interval_minutes,
|
|
14
|
+
:increase_factor,
|
|
15
|
+
:decrease_factor,
|
|
16
|
+
:failure_increase_factor,
|
|
17
|
+
:jitter_percent,
|
|
18
|
+
:stale_threshold_hours # ADD: new accessor
|
|
19
|
+
|
|
20
|
+
def reset!
|
|
21
|
+
@min_interval_minutes = 5
|
|
22
|
+
@max_interval_minutes = 24 * 60
|
|
23
|
+
@increase_factor = 1.25
|
|
24
|
+
@decrease_factor = 0.75
|
|
25
|
+
@failure_increase_factor = 1.5
|
|
26
|
+
@jitter_percent = 0.1
|
|
27
|
+
@stale_threshold_hours = 48 # ADD: default value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Step 2: Write tests**
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
# test/lib/source_monitor/configuration_test.rb
|
|
36
|
+
|
|
37
|
+
test "stale_threshold_hours has correct default" do
|
|
38
|
+
assert_equal 48, SourceMonitor.config.fetching.stale_threshold_hours
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test "stale_threshold_hours can be overridden" do
|
|
42
|
+
SourceMonitor.configure do |config|
|
|
43
|
+
config.fetching.stale_threshold_hours = 72
|
|
44
|
+
end
|
|
45
|
+
assert_equal 72, SourceMonitor.config.fetching.stale_threshold_hours
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
test "stale_threshold_hours resets with configuration" do
|
|
49
|
+
SourceMonitor.configure do |config|
|
|
50
|
+
config.fetching.stale_threshold_hours = 72
|
|
51
|
+
end
|
|
52
|
+
SourceMonitor.reset_configuration!
|
|
53
|
+
assert_equal 48, SourceMonitor.config.fetching.stale_threshold_hours
|
|
54
|
+
end
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Step 3: Run tests**
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/configuration_test.rb
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Scenario B: Add Setting with Validation
|
|
66
|
+
|
|
67
|
+
### Example: Add validated `strategy` to a section
|
|
68
|
+
|
|
69
|
+
**Step 1: Edit the settings file with custom setter**
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
class MySettings
|
|
73
|
+
VALID_MODES = %i[fast balanced thorough].freeze
|
|
74
|
+
|
|
75
|
+
attr_reader :mode
|
|
76
|
+
|
|
77
|
+
def initialize
|
|
78
|
+
reset!
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def mode=(value)
|
|
82
|
+
normalized = value&.to_sym
|
|
83
|
+
unless VALID_MODES.include?(normalized)
|
|
84
|
+
raise ArgumentError, "Invalid mode #{value.inspect}. Must be one of: #{VALID_MODES.join(', ')}"
|
|
85
|
+
end
|
|
86
|
+
@mode = normalized
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def reset!
|
|
90
|
+
@mode = :balanced
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Step 2: Write tests for all paths**
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
test "mode defaults to balanced" do
|
|
99
|
+
assert_equal :balanced, SourceMonitor.config.my_section.mode
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
test "mode accepts valid values" do
|
|
103
|
+
%i[fast balanced thorough].each do |mode|
|
|
104
|
+
SourceMonitor.configure do |config|
|
|
105
|
+
config.my_section.mode = mode
|
|
106
|
+
end
|
|
107
|
+
assert_equal mode, SourceMonitor.config.my_section.mode
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
test "mode accepts string values" do
|
|
112
|
+
SourceMonitor.configure do |config|
|
|
113
|
+
config.my_section.mode = "fast"
|
|
114
|
+
end
|
|
115
|
+
assert_equal :fast, SourceMonitor.config.my_section.mode
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
test "mode rejects invalid values" do
|
|
119
|
+
assert_raises(ArgumentError, /Invalid mode/) do
|
|
120
|
+
SourceMonitor.configure do |config|
|
|
121
|
+
config.my_section.mode = :invalid
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Scenario C: Add Setting with Normalization
|
|
130
|
+
|
|
131
|
+
### Example: Numeric setting that normalizes edge cases
|
|
132
|
+
|
|
133
|
+
Follow the `ScrapingSettings` pattern:
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
class MySettings
|
|
137
|
+
DEFAULT_LIMIT = 50
|
|
138
|
+
|
|
139
|
+
attr_reader :limit
|
|
140
|
+
|
|
141
|
+
def initialize
|
|
142
|
+
reset!
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def limit=(value)
|
|
146
|
+
@limit = normalize_numeric(value)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def reset!
|
|
150
|
+
@limit = DEFAULT_LIMIT
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
def normalize_numeric(value)
|
|
156
|
+
return nil if value.nil?
|
|
157
|
+
return nil if value == ""
|
|
158
|
+
integer = value.respond_to?(:to_i) ? value.to_i : value
|
|
159
|
+
integer.positive? ? integer : nil
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Test normalization edge cases:**
|
|
165
|
+
|
|
166
|
+
```ruby
|
|
167
|
+
test "limit normalizes string to integer" do
|
|
168
|
+
SourceMonitor.configure { |c| c.my_section.limit = "10" }
|
|
169
|
+
assert_equal 10, SourceMonitor.config.my_section.limit
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
test "limit normalizes nil to nil" do
|
|
173
|
+
SourceMonitor.configure { |c| c.my_section.limit = nil }
|
|
174
|
+
assert_nil SourceMonitor.config.my_section.limit
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
test "limit normalizes empty string to nil" do
|
|
178
|
+
SourceMonitor.configure { |c| c.my_section.limit = "" }
|
|
179
|
+
assert_nil SourceMonitor.config.my_section.limit
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
test "limit normalizes zero to nil" do
|
|
183
|
+
SourceMonitor.configure { |c| c.my_section.limit = 0 }
|
|
184
|
+
assert_nil SourceMonitor.config.my_section.limit
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
test "limit normalizes negative to nil" do
|
|
188
|
+
SourceMonitor.configure { |c| c.my_section.limit = -5 }
|
|
189
|
+
assert_nil SourceMonitor.config.my_section.limit
|
|
190
|
+
end
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Scenario D: Create a New Settings Section
|
|
196
|
+
|
|
197
|
+
### Step 1: Create the settings file
|
|
198
|
+
|
|
199
|
+
```ruby
|
|
200
|
+
# lib/source_monitor/configuration/notifications_settings.rb
|
|
201
|
+
# frozen_string_literal: true
|
|
202
|
+
|
|
203
|
+
module SourceMonitor
|
|
204
|
+
class Configuration
|
|
205
|
+
class NotificationsSettings
|
|
206
|
+
attr_accessor :enabled, :channels, :throttle_seconds
|
|
207
|
+
|
|
208
|
+
def initialize
|
|
209
|
+
reset!
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def reset!
|
|
213
|
+
@enabled = true
|
|
214
|
+
@channels = []
|
|
215
|
+
@throttle_seconds = 60
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Step 2: Add require and reader to Configuration
|
|
223
|
+
|
|
224
|
+
```ruby
|
|
225
|
+
# lib/source_monitor/configuration.rb
|
|
226
|
+
|
|
227
|
+
# At the top, add require:
|
|
228
|
+
require "source_monitor/configuration/notifications_settings"
|
|
229
|
+
|
|
230
|
+
# In the class:
|
|
231
|
+
attr_reader :http, :scrapers, :retention, :events, :models,
|
|
232
|
+
:realtime, :fetching, :health, :authentication, :scraping,
|
|
233
|
+
:notifications
|
|
234
|
+
|
|
235
|
+
# In initialize:
|
|
236
|
+
def initialize
|
|
237
|
+
# ... existing ...
|
|
238
|
+
@notifications = NotificationsSettings.new
|
|
239
|
+
end
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Step 3: Write tests
|
|
243
|
+
|
|
244
|
+
```ruby
|
|
245
|
+
# test/lib/source_monitor/configuration_test.rb
|
|
246
|
+
|
|
247
|
+
test "notifications settings have correct defaults" do
|
|
248
|
+
settings = SourceMonitor.config.notifications
|
|
249
|
+
assert_equal true, settings.enabled
|
|
250
|
+
assert_equal [], settings.channels
|
|
251
|
+
assert_equal 60, settings.throttle_seconds
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
test "notifications settings can be configured" do
|
|
255
|
+
SourceMonitor.configure do |config|
|
|
256
|
+
config.notifications.enabled = false
|
|
257
|
+
config.notifications.channels = [:email]
|
|
258
|
+
config.notifications.throttle_seconds = 30
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
settings = SourceMonitor.config.notifications
|
|
262
|
+
assert_equal false, settings.enabled
|
|
263
|
+
assert_equal [:email], settings.channels
|
|
264
|
+
assert_equal 30, settings.throttle_seconds
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
test "notifications reset restores defaults" do
|
|
268
|
+
SourceMonitor.configure do |config|
|
|
269
|
+
config.notifications.enabled = false
|
|
270
|
+
end
|
|
271
|
+
SourceMonitor.reset_configuration!
|
|
272
|
+
assert_equal true, SourceMonitor.config.notifications.enabled
|
|
273
|
+
end
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Step 4: Run tests
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/configuration_test.rb
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Checklist for Any New Setting
|
|
285
|
+
|
|
286
|
+
- [ ] Attribute added to settings class (attr_accessor or custom setter)
|
|
287
|
+
- [ ] Default value set in `reset!` (or `initialize` for classes without `reset!`)
|
|
288
|
+
- [ ] require statement added (if new file)
|
|
289
|
+
- [ ] Reader method exposed on Configuration (if new section)
|
|
290
|
+
- [ ] Initialization in Configuration#initialize (if new section)
|
|
291
|
+
- [ ] Tests: default value is correct
|
|
292
|
+
- [ ] Tests: value can be overridden
|
|
293
|
+
- [ ] Tests: reset restores default
|
|
294
|
+
- [ ] Tests: validation raises ArgumentError (if applicable)
|
|
295
|
+
- [ ] Tests: edge cases for normalization (if applicable)
|
|
296
|
+
- [ ] All tests pass: `PARALLEL_WORKERS=1 bin/rails test test/lib/source_monitor/configuration_test.rb`
|
|
297
|
+
- [ ] RuboCop clean: `bin/rubocop lib/source_monitor/configuration/`
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sm-configure
|
|
3
|
+
description: Use when configuring SourceMonitor engine settings via the DSL, including queue settings, HTTP client, fetching, health, scrapers, retention, scraping controls, events, model extensions, realtime, and authentication.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# sm-configure: Engine Configuration DSL
|
|
8
|
+
|
|
9
|
+
Comprehensive reference for configuring SourceMonitor via `SourceMonitor.configure`.
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
|
|
13
|
+
- Adding or modifying settings in `config/initializers/source_monitor.rb`
|
|
14
|
+
- Understanding what configuration options are available
|
|
15
|
+
- Debugging configuration-related issues
|
|
16
|
+
- Setting up environment-specific overrides
|
|
17
|
+
|
|
18
|
+
## Configuration Entry Point
|
|
19
|
+
|
|
20
|
+
All configuration lives inside the `configure` block in the host app's initializer:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
SourceMonitor.configure do |config|
|
|
24
|
+
# settings here
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
After the block executes, `ModelExtensions.reload!` runs automatically to apply any model changes. Restart web and worker processes after changes.
|
|
29
|
+
|
|
30
|
+
## Configuration Sections
|
|
31
|
+
|
|
32
|
+
The `config` object (`SourceMonitor::Configuration`) has 10 sub-sections plus top-level queue/job settings:
|
|
33
|
+
|
|
34
|
+
| Section | Accessor | Class |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| Top-level | `config.*` | `Configuration` |
|
|
37
|
+
| HTTP | `config.http` | `HTTPSettings` |
|
|
38
|
+
| Fetching | `config.fetching` | `FetchingSettings` |
|
|
39
|
+
| Health | `config.health` | `HealthSettings` |
|
|
40
|
+
| Scrapers | `config.scrapers` | `ScraperRegistry` |
|
|
41
|
+
| Retention | `config.retention` | `RetentionSettings` |
|
|
42
|
+
| Scraping | `config.scraping` | `ScrapingSettings` |
|
|
43
|
+
| Events | `config.events` | `Events` |
|
|
44
|
+
| Models | `config.models` | `Models` |
|
|
45
|
+
| Realtime | `config.realtime` | `RealtimeSettings` |
|
|
46
|
+
| Authentication | `config.authentication` | `AuthenticationSettings` |
|
|
47
|
+
|
|
48
|
+
See `reference/configuration-reference.md` for every setting with types, defaults, and examples.
|
|
49
|
+
|
|
50
|
+
## Quick Examples
|
|
51
|
+
|
|
52
|
+
### Queue Configuration
|
|
53
|
+
```ruby
|
|
54
|
+
config.queue_namespace = "source_monitor"
|
|
55
|
+
config.fetch_queue_name = "source_monitor_fetch"
|
|
56
|
+
config.fetch_queue_concurrency = 4
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### HTTP Client
|
|
60
|
+
```ruby
|
|
61
|
+
config.http.timeout = 30
|
|
62
|
+
config.http.proxy = ENV["HTTP_PROXY"]
|
|
63
|
+
config.http.retry_max = 3
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Authentication (Devise)
|
|
67
|
+
```ruby
|
|
68
|
+
config.authentication.authenticate_with :authenticate_user!
|
|
69
|
+
config.authentication.authorize_with ->(c) { c.current_user&.admin? }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Events
|
|
73
|
+
```ruby
|
|
74
|
+
config.events.after_item_created { |e| Notifier.new_item(e.item) }
|
|
75
|
+
config.events.register_item_processor ->(ctx) { Indexer.index(ctx.item) }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Model Extensions
|
|
79
|
+
```ruby
|
|
80
|
+
config.models.table_name_prefix = "sm_"
|
|
81
|
+
config.models.source.include_concern "MyApp::SourceExtension"
|
|
82
|
+
config.models.item.validate :custom_check
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Realtime
|
|
86
|
+
```ruby
|
|
87
|
+
config.realtime.adapter = :redis
|
|
88
|
+
config.realtime.redis_url = ENV["REDIS_URL"]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Helper APIs
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
SourceMonitor.config # Current configuration
|
|
95
|
+
SourceMonitor.configure { |c| ... } # Set configuration
|
|
96
|
+
SourceMonitor.reset_configuration! # Revert to defaults (for tests)
|
|
97
|
+
SourceMonitor.events # Shortcut to config.events
|
|
98
|
+
SourceMonitor.queue_name(:fetch) # Resolved queue name
|
|
99
|
+
SourceMonitor.queue_concurrency(:scrape) # Resolved concurrency
|
|
100
|
+
SourceMonitor.mission_control_dashboard_path # Resolved MC path or nil
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Key Source Files
|
|
104
|
+
|
|
105
|
+
| File | Purpose |
|
|
106
|
+
|---|---|
|
|
107
|
+
| `lib/source_monitor/configuration.rb` | Main Configuration class |
|
|
108
|
+
| `lib/source_monitor/configuration/http_settings.rb` | HTTP client settings |
|
|
109
|
+
| `lib/source_monitor/configuration/fetching_settings.rb` | Adaptive scheduling |
|
|
110
|
+
| `lib/source_monitor/configuration/health_settings.rb` | Health monitoring |
|
|
111
|
+
| `lib/source_monitor/configuration/scraper_registry.rb` | Scraper adapter registry |
|
|
112
|
+
| `lib/source_monitor/configuration/retention_settings.rb` | Item retention |
|
|
113
|
+
| `lib/source_monitor/configuration/scraping_settings.rb` | Scraping controls |
|
|
114
|
+
| `lib/source_monitor/configuration/events.rb` | Event callbacks |
|
|
115
|
+
| `lib/source_monitor/configuration/models.rb` | Model extensions config |
|
|
116
|
+
| `lib/source_monitor/configuration/model_definition.rb` | Per-model definition |
|
|
117
|
+
| `lib/source_monitor/configuration/realtime_settings.rb` | Action Cable settings |
|
|
118
|
+
| `lib/source_monitor/configuration/authentication_settings.rb` | Auth settings |
|
|
119
|
+
| `lib/source_monitor/configuration/validation_definition.rb` | Validation wrapper |
|
|
120
|
+
|
|
121
|
+
## References
|
|
122
|
+
|
|
123
|
+
- `reference/configuration-reference.md` -- Complete settings reference
|
|
124
|
+
- `docs/configuration.md` -- Official configuration documentation
|
|
125
|
+
- `lib/generators/source_monitor/install/templates/source_monitor.rb.tt` -- Initializer template
|
|
126
|
+
|
|
127
|
+
## Testing
|
|
128
|
+
|
|
129
|
+
Reset configuration between tests:
|
|
130
|
+
```ruby
|
|
131
|
+
setup do
|
|
132
|
+
SourceMonitor.reset_configuration!
|
|
133
|
+
end
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Test custom configuration:
|
|
137
|
+
```ruby
|
|
138
|
+
test "custom queue name" do
|
|
139
|
+
SourceMonitor.configure do |config|
|
|
140
|
+
config.fetch_queue_name = "custom_fetch"
|
|
141
|
+
end
|
|
142
|
+
assert_equal "custom_fetch", SourceMonitor.queue_name(:fetch)
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Checklist
|
|
147
|
+
|
|
148
|
+
- [ ] Initializer exists at `config/initializers/source_monitor.rb`
|
|
149
|
+
- [ ] Queue names match `config/solid_queue.yml` entries
|
|
150
|
+
- [ ] Authentication hooks configured for host auth system
|
|
151
|
+
- [ ] HTTP timeouts appropriate for target feeds
|
|
152
|
+
- [ ] Retention policy set for production
|
|
153
|
+
- [ ] Workers restarted after configuration changes
|