feat(alerting): countExecutionsForAlerting for exchange-match evaluator

Adds AlertMatchSpec record (core) and ClickHouseSearchIndex.countExecutionsForAlerting —
no FINAL, no text subqueries. Filters by tenant, env, app, route, status, time window,
and optional after-cursor. Attributes (JSON string column) use inlined JSONExtractString
key literals since ClickHouse JDBC does not bind ? placeholders inside JSON functions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-19 19:18:49 +02:00
parent 44e91ccdb5
commit 7b79d3aa64
3 changed files with 220 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
package com.cameleer.server.core.alerting;
import java.time.Instant;
import java.util.Map;
/**
* Specification for alerting-specific execution counting.
* Distinct from {@code SearchRequest}: no text-in-body subqueries, no cursor, no {@code FINAL}.
* All fields except {@code tenantId}, {@code environment}, {@code from}, and {@code to} are nullable filters.
*/
public record AlertMatchSpec(
String tenantId,
String environment,
String applicationId, // nullable — omit to match all apps
String routeId, // nullable — omit to match all routes
String status, // "FAILED" / "COMPLETED" / null for any
Map<String, String> attributes, // exact match on execution attribute key=value; empty = no filter
Instant from,
Instant to,
Instant after // nullable; used by PER_EXCHANGE mode to advance cursor past last seen
) {
public AlertMatchSpec {
attributes = attributes == null ? Map.of() : Map.copyOf(attributes);
}
}