fix(test): rewrite SearchControllerIT seed to chunks + fix GET auth scope
Largest Cluster B test: seeded 10 executions via the legacy RouteExecution shape which ChunkIngestionController silently degenerates to empty chunks, then verified via a Postgres SELECT against a ClickHouse table. Both failure modes addressed: - All 10 seed payloads are now ExecutionChunk envelopes (chunkSeq=0, final=true, flat processors[]). - Pipeline visibility probe is the env-scoped search REST endpoint (polling for the last corr-page-10 row). - searchGet() helper was using the AGENT token; env-scoped read endpoints require VIEWER+, so it now uses viewerJwt (matches what searchPost already did). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,22 +50,24 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
// Execution 1: COMPLETED, short duration, no errors
|
||||
ingest("""
|
||||
{
|
||||
"routeId": "search-route-1",
|
||||
"exchangeId": "ex-search-1",
|
||||
"applicationId": "test-group",
|
||||
"instanceId": "test-agent-search-it",
|
||||
"routeId": "search-route-1",
|
||||
"correlationId": "corr-alpha",
|
||||
"status": "COMPLETED",
|
||||
"startTime": "2026-03-10T10:00:00Z",
|
||||
"endTime": "2026-03-10T10:00:00.050Z",
|
||||
"durationMs": 50,
|
||||
"errorMessage": "",
|
||||
"errorStackTrace": "",
|
||||
"chunkSeq": 0,
|
||||
"final": true,
|
||||
"processors": [
|
||||
{
|
||||
"seq": 1,
|
||||
"processorId": "proc-1",
|
||||
"processorType": "log",
|
||||
"status": "COMPLETED",
|
||||
"startTime": "2026-03-10T10:00:00Z",
|
||||
"endTime": "2026-03-10T10:00:00.050Z",
|
||||
"durationMs": 50,
|
||||
"inputBody": "customer-123 order data",
|
||||
"outputBody": "processed customer-123",
|
||||
@@ -79,8 +81,10 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
// Execution 2: FAILED with NullPointerException, medium duration
|
||||
ingest("""
|
||||
{
|
||||
"routeId": "search-route-2",
|
||||
"exchangeId": "ex-search-2",
|
||||
"applicationId": "test-group",
|
||||
"instanceId": "test-agent-search-it",
|
||||
"routeId": "search-route-2",
|
||||
"correlationId": "corr-beta",
|
||||
"status": "FAILED",
|
||||
"startTime": "2026-03-10T12:00:00Z",
|
||||
@@ -88,6 +92,8 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
"durationMs": 200,
|
||||
"errorMessage": "NullPointerException in OrderService",
|
||||
"errorStackTrace": "java.lang.NullPointerException\\n at com.example.OrderService.process(OrderService.java:42)",
|
||||
"chunkSeq": 0,
|
||||
"final": true,
|
||||
"processors": []
|
||||
}
|
||||
""");
|
||||
@@ -95,15 +101,17 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
// Execution 3: RUNNING, long duration, different time window
|
||||
ingest("""
|
||||
{
|
||||
"routeId": "search-route-3",
|
||||
"exchangeId": "ex-search-3",
|
||||
"applicationId": "test-group",
|
||||
"instanceId": "test-agent-search-it",
|
||||
"routeId": "search-route-3",
|
||||
"correlationId": "corr-gamma",
|
||||
"status": "RUNNING",
|
||||
"startTime": "2026-03-11T08:00:00Z",
|
||||
"endTime": "2026-03-11T08:00:01Z",
|
||||
"durationMs": 1000,
|
||||
"errorMessage": "",
|
||||
"errorStackTrace": "",
|
||||
"chunkSeq": 0,
|
||||
"final": true,
|
||||
"processors": []
|
||||
}
|
||||
""");
|
||||
@@ -111,8 +119,10 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
// Execution 4: FAILED with MyException in stack trace
|
||||
ingest("""
|
||||
{
|
||||
"routeId": "search-route-4",
|
||||
"exchangeId": "ex-search-4",
|
||||
"applicationId": "test-group",
|
||||
"instanceId": "test-agent-search-it",
|
||||
"routeId": "search-route-4",
|
||||
"correlationId": "corr-delta",
|
||||
"status": "FAILED",
|
||||
"startTime": "2026-03-10T14:00:00Z",
|
||||
@@ -120,18 +130,17 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
"durationMs": 300,
|
||||
"errorMessage": "Processing failed",
|
||||
"errorStackTrace": "com.example.MyException: something broke\\n at com.example.Handler.handle(Handler.java:10)",
|
||||
"chunkSeq": 0,
|
||||
"final": true,
|
||||
"processors": [
|
||||
{
|
||||
"seq": 1,
|
||||
"processorId": "proc-4",
|
||||
"processorType": "bean",
|
||||
"status": "FAILED",
|
||||
"startTime": "2026-03-10T14:00:00Z",
|
||||
"endTime": "2026-03-10T14:00:00.300Z",
|
||||
"durationMs": 300,
|
||||
"inputBody": "",
|
||||
"outputBody": "",
|
||||
"inputHeaders": {"Content-Type": "text/plain"},
|
||||
"outputHeaders": {}
|
||||
"inputHeaders": {"Content-Type": "text/plain"}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -141,28 +150,25 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
for (int i = 5; i <= 10; i++) {
|
||||
ingest(String.format("""
|
||||
{
|
||||
"routeId": "search-route-%d",
|
||||
"exchangeId": "ex-search-%d",
|
||||
"applicationId": "test-group",
|
||||
"instanceId": "test-agent-search-it",
|
||||
"routeId": "search-route-%d",
|
||||
"correlationId": "corr-page-%d",
|
||||
"status": "COMPLETED",
|
||||
"startTime": "2026-03-10T15:00:%02d.000Z",
|
||||
"endTime": "2026-03-10T15:00:%02d.100Z",
|
||||
"durationMs": 100,
|
||||
"errorMessage": "",
|
||||
"errorStackTrace": "",
|
||||
"chunkSeq": 0,
|
||||
"final": true,
|
||||
"processors": []
|
||||
}
|
||||
""", i, i, i, i, i));
|
||||
}
|
||||
|
||||
// Verify all data is in PostgreSQL (synchronous writes)
|
||||
Integer count = jdbcTemplate.queryForObject(
|
||||
"SELECT count(*) FROM executions WHERE route_id LIKE 'search-route-%'",
|
||||
Integer.class);
|
||||
assertThat(count).isEqualTo(10);
|
||||
|
||||
// Wait for async search indexing (debounce + index time)
|
||||
// Check for last seeded execution specifically to avoid false positives from other test classes
|
||||
// Wait for async ingestion + search indexing via REST (no raw SQL).
|
||||
// Probe the last seeded execution to avoid false positives from
|
||||
// other test classes that may have written into the shared CH tables.
|
||||
await().atMost(30, SECONDS).untilAsserted(() -> {
|
||||
ResponseEntity<String> r = searchGet("?correlationId=corr-page-10");
|
||||
JsonNode body = objectMapper.readTree(r.getBody());
|
||||
@@ -373,7 +379,9 @@ class SearchControllerIT extends AbstractPostgresIT {
|
||||
}
|
||||
|
||||
private ResponseEntity<String> searchGet(String queryString) {
|
||||
HttpHeaders headers = securityHelper.authHeadersNoBody(jwt);
|
||||
// GET /api/v1/environments/*/executions/** requires VIEWER+ — use the
|
||||
// viewer token, not the agent token (agent would get 403 FORBIDDEN).
|
||||
HttpHeaders headers = securityHelper.authHeadersNoBody(viewerJwt);
|
||||
return restTemplate.exchange(
|
||||
"/api/v1/environments/default/executions" + queryString,
|
||||
HttpMethod.GET,
|
||||
|
||||
Reference in New Issue
Block a user