From e483e52eee33a8e1cd097316b485997cf1d296e6 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Wed, 22 Apr 2026 17:10:53 +0200 Subject: [PATCH] alerting(core): drop unused perExchangeLingerSeconds from ExchangeMatchCondition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dead field — was enforced by compact ctor as required for PER_EXCHANGE, but never read anywhere in the codebase. Removal tightens the API surface and is precondition for the Task 3.3 cross-field validator. Pre-prod; no shim / migration. --- .../controller/AlertRuleControllerIT.java | 4 ++-- .../app/alerting/eval/AlertEvaluatorJobIT.java | 2 +- .../eval/ExchangeMatchEvaluatorTest.java | 16 ++++++++-------- .../notify/NotificationContextBuilderTest.java | 2 +- .../core/alerting/ExchangeMatchCondition.java | 5 +---- .../core/alerting/AlertConditionJsonTest.java | 9 ++++----- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/controller/AlertRuleControllerIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/controller/AlertRuleControllerIT.java index 7275a588..8757bda9 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/controller/AlertRuleControllerIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/controller/AlertRuleControllerIT.java @@ -145,7 +145,7 @@ class AlertRuleControllerIT extends AbstractPostgresIT { {"name":"sqli-test","severity":"WARNING","conditionKind":"EXCHANGE_MATCH", "condition":{"kind":"EXCHANGE_MATCH","scope":{}, "filter":{"status":"FAILED","attributes":{"foo'; DROP TABLE executions; --":"x"}}, - "fireMode":"PER_EXCHANGE","perExchangeLingerSeconds":60}} + "fireMode":"PER_EXCHANGE"}} """; ResponseEntity resp = restTemplate.exchange( @@ -164,7 +164,7 @@ class AlertRuleControllerIT extends AbstractPostgresIT { {"name":"valid-attr","severity":"WARNING","conditionKind":"EXCHANGE_MATCH", "condition":{"kind":"EXCHANGE_MATCH","scope":{}, "filter":{"status":"FAILED","attributes":{"order.type":"x"}}, - "fireMode":"PER_EXCHANGE","perExchangeLingerSeconds":60}} + "fireMode":"PER_EXCHANGE"}} """; ResponseEntity resp = restTemplate.exchange( diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/AlertEvaluatorJobIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/AlertEvaluatorJobIT.java index 550b4684..d8e78592 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/AlertEvaluatorJobIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/AlertEvaluatorJobIT.java @@ -158,7 +158,7 @@ class AlertEvaluatorJobIT extends AbstractPostgresIT { var condition = new ExchangeMatchCondition( new AlertScope(APP_SLUG, null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.PER_EXCHANGE, null, null, 60); + FireMode.PER_EXCHANGE, null, null); var webhook = new WebhookBinding(UUID.randomUUID(), null, null, Map.of()); var rule = new AlertRule( ruleId2, envId, "per-exchange-rule-" + ruleId2, null, diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/ExchangeMatchEvaluatorTest.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/ExchangeMatchEvaluatorTest.java index 6096bbe1..33bb64f4 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/ExchangeMatchEvaluatorTest.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/eval/ExchangeMatchEvaluatorTest.java @@ -61,7 +61,7 @@ class ExchangeMatchEvaluatorTest { return new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.PER_EXCHANGE, null, null, 60); + FireMode.PER_EXCHANGE, null, null); } private ExecutionSummary summary(String id, Instant startTime, String status) { @@ -77,7 +77,7 @@ class ExchangeMatchEvaluatorTest { var condition = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.COUNT_IN_WINDOW, 5, 300, null); + FireMode.COUNT_IN_WINDOW, 5, 300); when(searchIndex.countExecutionsForAlerting(any())).thenReturn(7L); @@ -92,7 +92,7 @@ class ExchangeMatchEvaluatorTest { var condition = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.COUNT_IN_WINDOW, 5, 300, null); + FireMode.COUNT_IN_WINDOW, 5, 300); when(searchIndex.countExecutionsForAlerting(any())).thenReturn(3L); @@ -105,7 +105,7 @@ class ExchangeMatchEvaluatorTest { var condition = new ExchangeMatchCondition( new AlertScope("orders", "direct:pay", null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of("orderId", "123")), - FireMode.COUNT_IN_WINDOW, 1, 120, null); + FireMode.COUNT_IN_WINDOW, 1, 120); when(searchIndex.countExecutionsForAlerting(any())).thenReturn(2L); @@ -132,7 +132,7 @@ class ExchangeMatchEvaluatorTest { var condition = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.PER_EXCHANGE, null, null, 60); + FireMode.PER_EXCHANGE, null, null); when(searchIndex.search(any())).thenReturn(SearchResult.empty(0, 50)); @@ -146,7 +146,7 @@ class ExchangeMatchEvaluatorTest { var condition = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.PER_EXCHANGE, null, null, 60); + FireMode.PER_EXCHANGE, null, null); Instant t1 = NOW.minusSeconds(50); Instant t2 = NOW.minusSeconds(30); @@ -170,7 +170,7 @@ class ExchangeMatchEvaluatorTest { var condition = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.PER_EXCHANGE, null, null, 60); + FireMode.PER_EXCHANGE, null, null); Instant t1 = NOW.minusSeconds(50); Instant t2 = NOW.minusSeconds(10); // latest @@ -193,7 +193,7 @@ class ExchangeMatchEvaluatorTest { var condition = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.PER_EXCHANGE, null, null, 60); + FireMode.PER_EXCHANGE, null, null); Instant cursor = NOW.minusSeconds(120); var rule = ruleWith(condition, Map.of("lastExchangeCursor", cursor.toString() + "|ex-prev")); diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/notify/NotificationContextBuilderTest.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/notify/NotificationContextBuilderTest.java index e67c4834..c11b2142 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/notify/NotificationContextBuilderTest.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/alerting/notify/NotificationContextBuilderTest.java @@ -39,7 +39,7 @@ class NotificationContextBuilderTest { case EXCHANGE_MATCH -> new ExchangeMatchCondition( new AlertScope("my-app", "route-1", null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.PER_EXCHANGE, null, null, 30); + FireMode.PER_EXCHANGE, null, null); case AGENT_STATE -> new AgentStateCondition( new AlertScope(null, null, null), "DEAD", 0); diff --git a/cameleer-server-core/src/main/java/com/cameleer/server/core/alerting/ExchangeMatchCondition.java b/cameleer-server-core/src/main/java/com/cameleer/server/core/alerting/ExchangeMatchCondition.java index e8a56cc8..c823ee3a 100644 --- a/cameleer-server-core/src/main/java/com/cameleer/server/core/alerting/ExchangeMatchCondition.java +++ b/cameleer-server-core/src/main/java/com/cameleer/server/core/alerting/ExchangeMatchCondition.java @@ -9,8 +9,7 @@ public record ExchangeMatchCondition( ExchangeFilter filter, FireMode fireMode, Integer threshold, // required when COUNT_IN_WINDOW; null for PER_EXCHANGE - Integer windowSeconds, // required when COUNT_IN_WINDOW - Integer perExchangeLingerSeconds // required when PER_EXCHANGE + Integer windowSeconds // required when COUNT_IN_WINDOW ) implements AlertCondition { public ExchangeMatchCondition { @@ -18,8 +17,6 @@ public record ExchangeMatchCondition( throw new IllegalArgumentException("fireMode is required (PER_EXCHANGE or COUNT_IN_WINDOW)"); if (fireMode == FireMode.COUNT_IN_WINDOW && (threshold == null || windowSeconds == null)) throw new IllegalArgumentException("COUNT_IN_WINDOW requires threshold + windowSeconds"); - if (fireMode == FireMode.PER_EXCHANGE && perExchangeLingerSeconds == null) - throw new IllegalArgumentException("PER_EXCHANGE requires perExchangeLingerSeconds"); } @Override diff --git a/cameleer-server-core/src/test/java/com/cameleer/server/core/alerting/AlertConditionJsonTest.java b/cameleer-server-core/src/test/java/com/cameleer/server/core/alerting/AlertConditionJsonTest.java index 950720a0..ca7489e0 100644 --- a/cameleer-server-core/src/test/java/com/cameleer/server/core/alerting/AlertConditionJsonTest.java +++ b/cameleer-server-core/src/test/java/com/cameleer/server/core/alerting/AlertConditionJsonTest.java @@ -28,7 +28,7 @@ class AlertConditionJsonTest { var c = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of("type","payment")), - FireMode.PER_EXCHANGE, null, null, 300); + FireMode.PER_EXCHANGE, null, null); String json = om.writeValueAsString((AlertCondition) c); AlertCondition parsed = om.readValue(json, AlertCondition.class); assertThat(parsed).isInstanceOf(ExchangeMatchCondition.class); @@ -39,7 +39,7 @@ class AlertConditionJsonTest { var c = new ExchangeMatchCondition( new AlertScope("orders", null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - FireMode.COUNT_IN_WINDOW, 5, 900, null); + FireMode.COUNT_IN_WINDOW, 5, 900); AlertCondition parsed = om.readValue(om.writeValueAsString((AlertCondition) c), AlertCondition.class); assertThat(((ExchangeMatchCondition) parsed).threshold()).isEqualTo(5); } @@ -49,7 +49,7 @@ class AlertConditionJsonTest { assertThatThrownBy(() -> new ExchangeMatchCondition( new AlertScope(null, null, null), new ExchangeMatchCondition.ExchangeFilter("FAILED", Map.of()), - null, null, null, null)) + null, null, null)) .isInstanceOf(IllegalArgumentException.class) .hasMessageContaining("fireMode"); } @@ -63,8 +63,7 @@ class AlertConditionJsonTest { "filter": {"status": "FAILED", "attributes": {}}, "fireMode": null, "threshold": null, - "windowSeconds": null, - "perExchangeLingerSeconds": null + "windowSeconds": null } """; assertThatThrownBy(() -> om.readValue(json, AlertCondition.class))