feat(alerting): Plan 02 — backend (domain, storage, evaluators, dispatch) #140

Merged
claude merged 53 commits from feat/alerting-02-backend into main 2026-04-20 09:03:16 +02:00
2 changed files with 18 additions and 14 deletions
Showing only changes of commit 8bf45d5456 - Show all commits

View File

@@ -1,12 +1,12 @@
-- Alerting projections — additive and idempotent (IF NOT EXISTS). -- Alerting projections — additive and idempotent (IF NOT EXISTS).
-- Safe to run on every startup alongside init.sql. -- Safe to run on every startup alongside init.sql.
-- --
-- NOTE: executions uses ReplacingMergeTree which requires deduplicate_merge_projection_mode='rebuild' -- executions uses ReplacingMergeTree. ClickHouse 24.x requires deduplicate_merge_projection_mode='rebuild'
-- to support projections (ClickHouse 24.x). The ADD PROJECTION and MATERIALIZE statements for -- for projections to work on ReplacingMergeTree. ALTER TABLE MODIFY SETTING persists the setting in
-- executions are treated as best-effort by the schema initializer (non-fatal on failure). -- table metadata (survives restarts) and runs before the ADD PROJECTION statements.
-- logs and agent_metrics use plain MergeTree and always succeed. -- logs and agent_metrics use plain MergeTree and do not need this setting.
-- --
-- MATERIALIZE statements are also wrapped as non-fatal to handle empty tables in fresh deployments. -- MATERIALIZE statements are wrapped as non-fatal to handle empty tables in fresh deployments.
-- Plain MergeTree tables: always succeed -- Plain MergeTree tables: always succeed
ALTER TABLE logs ALTER TABLE logs
@@ -17,7 +17,9 @@ ALTER TABLE agent_metrics
ADD PROJECTION IF NOT EXISTS alerting_instance_metric ADD PROJECTION IF NOT EXISTS alerting_instance_metric
(SELECT * ORDER BY (tenant_id, environment, instance_id, metric_name, collected_at)); (SELECT * ORDER BY (tenant_id, environment, instance_id, metric_name, collected_at));
-- ReplacingMergeTree tables: best-effort (requires deduplicate_merge_projection_mode='rebuild') -- ReplacingMergeTree: set table-level setting so ADD PROJECTION succeeds on any connection
ALTER TABLE executions MODIFY SETTING deduplicate_merge_projection_mode = 'rebuild';
ALTER TABLE executions ALTER TABLE executions
ADD PROJECTION IF NOT EXISTS alerting_app_status ADD PROJECTION IF NOT EXISTS alerting_app_status
(SELECT * ORDER BY (tenant_id, environment, application_id, status, start_time)); (SELECT * ORDER BY (tenant_id, environment, application_id, status, start_time));

View File

@@ -34,17 +34,19 @@ class AlertingProjectionsIT {
} }
@Test @Test
void mergeTreeProjectionsExistAfterInit() { void allFourProjectionsExistAfterInit() {
// logs and agent_metrics are plain MergeTree — projections always succeed. // logs and agent_metrics are plain MergeTree — always succeed.
// executions is ReplacingMergeTree; its projections require the session setting // executions is ReplacingMergeTree; its projections now succeed because
// deduplicate_merge_projection_mode='rebuild' which is unavailable via JDBC pool, // alerting_projections.sql runs ALTER TABLE executions MODIFY SETTING
// so they are best-effort and not asserted here. // deduplicate_merge_projection_mode='rebuild' before the ADD PROJECTION statements.
List<String> names = jdbc.queryForList( List<String> names = jdbc.queryForList(
"SELECT name FROM system.projections WHERE table IN ('logs', 'agent_metrics')", "SELECT name FROM system.projections WHERE table IN ('logs', 'agent_metrics', 'executions')",
String.class); String.class);
assertThat(names).contains( assertThat(names).containsExactlyInAnyOrder(
"alerting_app_level", "alerting_app_level",
"alerting_instance_metric"); "alerting_instance_metric",
"alerting_app_status",
"alerting_route_status");
} }
} }