From dfacedb0ca18ca9ac77ce5e2ee92c571e91b0212 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:04:00 +0200 Subject: [PATCH] fix(test): rewrite DetailControllerIT seed to ExecutionChunk + REST-driven lookup POST /api/v1/data/executions is owned by ChunkIngestionController (the legacy ExecutionController path is @ConditionalOnMissingBean(ChunkAccumulator) and never binds). The old RouteExecution-shaped seed was silently parsed as an empty ExecutionChunk and nothing landed in ClickHouse. Rewrote the seed as a single final ExecutionChunk with chunkSeq=0 / final=true and a flat processors[] carrying seq + parentSeq to preserve the 3-level tree (DetailService.buildTree reconstructs the nested shape for the API response). Execution-id lookup now goes through the search REST API filtered by correlationId, per the no-raw-SQL preference. Template for the other Cluster B ITs. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../app/controller/DetailControllerIT.java | 119 ++++++++++-------- 1 file changed, 64 insertions(+), 55 deletions(-) diff --git a/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/DetailControllerIT.java b/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/DetailControllerIT.java index 6741f177..9fdbb4eb 100644 --- a/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/DetailControllerIT.java +++ b/cameleer-server-app/src/test/java/com/cameleer/server/app/controller/DetailControllerIT.java @@ -40,6 +40,12 @@ class DetailControllerIT extends AbstractPostgresIT { /** * Seed a route execution with a 3-level processor tree: * root -> [child1, child2], child2 -> [grandchild] + * + * Uses the chunked ingestion envelope (POST /api/v1/data/executions → + * ChunkIngestionController), which is the only active ingestion path. + * The processor tree is flattened into FlatProcessorRecord[] with + * seq / parentSeq; DetailService.buildTree reconstructs the nested + * shape for the API response. */ @BeforeAll void seedTestData() { @@ -48,67 +54,66 @@ class DetailControllerIT extends AbstractPostgresIT { String json = """ { - "routeId": "detail-test-route", "exchangeId": "detail-ex-1", + "applicationId": "test-group", + "instanceId": "test-agent-detail-it", + "routeId": "detail-test-route", "correlationId": "detail-corr-1", "status": "COMPLETED", "startTime": "2026-03-10T10:00:00Z", "endTime": "2026-03-10T10:00:01Z", "durationMs": 1000, - "errorMessage": "", - "errorStackTrace": "", + "chunkSeq": 0, + "final": true, "processors": [ { + "seq": 1, "processorId": "root-proc", "processorType": "split", "status": "COMPLETED", "startTime": "2026-03-10T10:00:00Z", - "endTime": "2026-03-10T10:00:01Z", "durationMs": 1000, "inputBody": "root-input-body", "outputBody": "root-output-body", "inputHeaders": {"Content-Type": "application/json"}, - "outputHeaders": {"X-Result": "ok"}, - "children": [ - { - "processorId": "child1-proc", - "processorType": "log", - "status": "COMPLETED", - "startTime": "2026-03-10T10:00:00.100Z", - "endTime": "2026-03-10T10:00:00.200Z", - "durationMs": 100, - "inputBody": "child1-input", - "outputBody": "child1-output", - "inputHeaders": {}, - "outputHeaders": {} - }, - { - "processorId": "child2-proc", - "processorType": "bean", - "status": "COMPLETED", - "startTime": "2026-03-10T10:00:00.200Z", - "endTime": "2026-03-10T10:00:00.800Z", - "durationMs": 600, - "inputBody": "child2-input", - "outputBody": "child2-output", - "inputHeaders": {}, - "outputHeaders": {}, - "children": [ - { - "processorId": "grandchild-proc", - "processorType": "to", - "status": "COMPLETED", - "startTime": "2026-03-10T10:00:00.300Z", - "endTime": "2026-03-10T10:00:00.700Z", - "durationMs": 400, - "inputBody": "gc-input", - "outputBody": "gc-output", - "inputHeaders": {"X-GC": "true"}, - "outputHeaders": {} - } - ] - } - ] + "outputHeaders": {"X-Result": "ok"} + }, + { + "seq": 2, + "parentSeq": 1, + "parentProcessorId": "root-proc", + "processorId": "child1-proc", + "processorType": "log", + "status": "COMPLETED", + "startTime": "2026-03-10T10:00:00.100Z", + "durationMs": 100, + "inputBody": "child1-input", + "outputBody": "child1-output" + }, + { + "seq": 3, + "parentSeq": 1, + "parentProcessorId": "root-proc", + "processorId": "child2-proc", + "processorType": "bean", + "status": "COMPLETED", + "startTime": "2026-03-10T10:00:00.200Z", + "durationMs": 600, + "inputBody": "child2-input", + "outputBody": "child2-output" + }, + { + "seq": 4, + "parentSeq": 3, + "parentProcessorId": "child2-proc", + "processorId": "grandchild-proc", + "processorType": "to", + "status": "COMPLETED", + "startTime": "2026-03-10T10:00:00.300Z", + "durationMs": 400, + "inputBody": "gc-input", + "outputBody": "gc-output", + "inputHeaders": {"X-GC": "true"} } ] } @@ -116,17 +121,21 @@ class DetailControllerIT extends AbstractPostgresIT { ingest(json); - // Wait for flush and get the execution_id - await().atMost(10, SECONDS).untilAsserted(() -> { - Integer count = jdbcTemplate.queryForObject( - "SELECT count(*) FROM executions WHERE route_id = 'detail-test-route'", - Integer.class); - assertThat(count).isGreaterThanOrEqualTo(1); + // Wait for async ingestion + flush, then pull the CH-assigned execution_id + // back through the REST search API. Executions live in ClickHouse; always + // drive CH assertions through REST so the test still covers the full + // controller→service→store wiring. + await().atMost(20, SECONDS).untilAsserted(() -> { + ResponseEntity r = restTemplate.exchange( + "/api/v1/environments/default/executions?correlationId=detail-corr-1", + HttpMethod.GET, + new HttpEntity<>(securityHelper.authHeadersNoBody(viewerJwt)), + String.class); + assertThat(r.getStatusCode()).isEqualTo(HttpStatus.OK); + JsonNode body = objectMapper.readTree(r.getBody()); + assertThat(body.get("total").asLong()).isGreaterThanOrEqualTo(1); + seededExecutionId = body.get("data").get(0).get("executionId").asText(); }); - - seededExecutionId = jdbcTemplate.queryForObject( - "SELECT execution_id FROM executions WHERE route_id = 'detail-test-route' LIMIT 1", - String.class); } @Test