Files
cameleer-server/.planning/phases/02-transaction-search-diagrams/02-03-PLAN.md
hsiegeln cb3ebfea7c
Some checks failed
CI / cleanup-branch (push) Has been skipped
CI / build (push) Failing after 18s
CI / docker (push) Has been skipped
CI / deploy (push) Has been skipped
CI / deploy-feature (push) Has been skipped
chore: rename cameleer3 to cameleer
Rename Java packages from com.cameleer3 to com.cameleer, module
directories from cameleer3-* to cameleer-*, and all references
throughout workflows, Dockerfiles, docs, migrations, and pom.xml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 15:28:42 +02:00

21 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
02-transaction-search-diagrams 03 execute 2
02-01
cameleer-server-app/src/main/java/com/cameleer/server/app/search/ClickHouseSearchEngine.java
cameleer-server-app/src/main/java/com/cameleer/server/app/controller/SearchController.java
cameleer-server-app/src/main/java/com/cameleer/server/app/controller/DetailController.java
cameleer-server-app/src/main/java/com/cameleer/server/app/config/SearchBeanConfig.java
cameleer-server-app/src/main/java/com/cameleer/server/app/storage/ClickHouseExecutionRepository.java
cameleer-server-app/src/test/java/com/cameleer/server/app/controller/SearchControllerIT.java
cameleer-server-app/src/test/java/com/cameleer/server/app/controller/DetailControllerIT.java
cameleer-server-core/src/test/java/com/cameleer/server/core/detail/TreeReconstructionTest.java
true
SRCH-01
SRCH-02
SRCH-03
SRCH-04
SRCH-05
SRCH-06
truths artifacts key_links
User can search by status and get only matching executions
User can search by time range and get only executions within that window
User can search by duration range (min/max ms) and get matching executions
User can search by correlationId to find all related executions
User can full-text search and find matches in bodies, headers, error messages, stack traces
User can combine multiple filters in a single search (e.g., status + time + text)
User can retrieve a transaction detail with nested processor execution tree
Detail response includes diagramContentHash for linking to diagram endpoint
Search results are paginated with total count, offset, and limit
path provides min_lines
cameleer-server-app/src/main/java/com/cameleer/server/app/search/ClickHouseSearchEngine.java ClickHouse implementation of SearchEngine with dynamic WHERE building 80
path provides exports
cameleer-server-app/src/main/java/com/cameleer/server/app/controller/SearchController.java GET + POST /api/v1/search/executions endpoints
SearchController
path provides exports
cameleer-server-app/src/main/java/com/cameleer/server/app/controller/DetailController.java GET /api/v1/executions/{id} endpoint returning nested tree
DetailController
path provides min_lines
cameleer-server-app/src/test/java/com/cameleer/server/app/controller/SearchControllerIT.java Integration tests for all search filter combinations 100
from to via pattern
SearchController SearchService constructor injection, delegates search() searchService.search
from to via pattern
SearchService ClickHouseSearchEngine SearchEngine interface engine.search
from to via pattern
ClickHouseSearchEngine route_executions table dynamic SQL with parameterized WHERE SELECT.*FROM route_executions.*WHERE
from to via pattern
DetailController DetailService constructor injection detailService.getDetail
from to via pattern
DetailService ClickHouseExecutionRepository findRawById for flat data, then reconstructTree findRawById|reconstructTree
Implement the search endpoints (GET and POST), the ClickHouse search engine with dynamic SQL, the transaction detail endpoint with nested tree reconstruction, and comprehensive integration tests.

Purpose: This is the core query capability of Phase 2 — users need to find transactions by any combination of filters and drill into execution details. The search engine abstraction allows future swap to OpenSearch.

Output: SearchController (GET + POST), DetailController, ClickHouseSearchEngine, TreeReconstructionTest, SearchControllerIT, DetailControllerIT.

<execution_context> @C:/Users/Hendrik/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/Hendrik/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/02-transaction-search-diagrams/02-CONTEXT.md @.planning/phases/02-transaction-search-diagrams/02-RESEARCH.md @.planning/phases/02-transaction-search-diagrams/02-01-SUMMARY.md

@clickhouse/init/01-schema.sql @clickhouse/init/02-search-columns.sql @cameleer-server-app/src/main/java/com/cameleer/server/app/storage/ClickHouseExecutionRepository.java @cameleer-server-app/src/main/java/com/cameleer/server/app/controller/ExecutionController.java

From cameleer-server-core/.../search/SearchEngine.java:

public interface SearchEngine {
    SearchResult<ExecutionSummary> search(SearchRequest request);
    long count(SearchRequest request);
}

From cameleer-server-core/.../search/SearchRequest.java:

public record SearchRequest(
    String status,          // nullable, filter by ExecutionStatus name
    Instant timeFrom,       // nullable, start_time >= this
    Instant timeTo,         // nullable, start_time <= this
    Long durationMin,       // nullable, duration_ms >= this
    Long durationMax,       // nullable, duration_ms <= this
    String correlationId,   // nullable, exact match
    String text,            // nullable, global full-text LIKE across all text fields
    String textInBody,      // nullable, LIKE on exchange_bodies only
    String textInHeaders,   // nullable, LIKE on exchange_headers only
    String textInErrors,    // nullable, LIKE on error_message + error_stacktrace
    int offset,
    int limit
) { /* compact constructor with validation */ }

From cameleer-server-core/.../search/SearchResult.java:

public record SearchResult<T>(List<T> data, long total, int offset, int limit) {
    public static <T> SearchResult<T> empty(int offset, int limit);
}

From cameleer-server-core/.../search/ExecutionSummary.java:

public record ExecutionSummary(
    String executionId, String routeId, String agentId, String status,
    Instant startTime, Instant endTime, long durationMs,
    String correlationId, String errorMessage, String diagramContentHash
) {}

From cameleer-server-core/.../detail/DetailService.java:

public class DetailService {
    // Constructor takes ExecutionRepository (or a query interface)
    public Optional<ExecutionDetail> getDetail(String executionId);
    // Internal: reconstructTree(parallel arrays) -> List<ProcessorNode>
}

From cameleer-server-core/.../detail/ExecutionDetail.java:

public record ExecutionDetail(
    String executionId, String routeId, String agentId, String status,
    Instant startTime, Instant endTime, long durationMs,
    String correlationId, String exchangeId, String errorMessage,
    String errorStackTrace, String diagramContentHash,
    List<ProcessorNode> processors
) {}

From cameleer-server-core/.../detail/ProcessorNode.java:

public record ProcessorNode(
    String processorId, String processorType, String status,
    Instant startTime, Instant endTime, long durationMs,
    String diagramNodeId, String errorMessage, String errorStackTrace,
    List<ProcessorNode> children
) {}

Existing ClickHouse schema (after Plan 01 schema extension):

-- route_executions columns:
-- execution_id, route_id, agent_id, status, start_time, end_time,
-- duration_ms, correlation_id, exchange_id, error_message, error_stacktrace,
-- processor_ids, processor_types, processor_starts, processor_ends,
-- processor_durations, processor_statuses,
-- exchange_bodies, exchange_headers,
-- processor_depths, processor_parent_indexes,
-- processor_error_messages, processor_error_stacktraces,
-- processor_input_bodies, processor_output_bodies,
-- processor_input_headers, processor_output_headers,
-- processor_diagram_node_ids, diagram_content_hash,
-- server_received_at
-- ORDER BY (agent_id, status, start_time, execution_id)

Established controller pattern (from Phase 1):

// Controllers accept raw String body for single/array flexibility
// Return 202 for ingestion, standard REST responses for queries
// ProtocolVersionInterceptor validates X-Cameleer-Protocol-Version: 1 header
Task 1: ClickHouseSearchEngine, SearchController, and search integration tests cameleer-server-app/src/main/java/com/cameleer/server/app/search/ClickHouseSearchEngine.java, cameleer-server-app/src/main/java/com/cameleer/server/app/controller/SearchController.java, cameleer-server-app/src/main/java/com/cameleer/server/app/config/SearchBeanConfig.java, cameleer-server-app/src/test/java/com/cameleer/server/app/controller/SearchControllerIT.java - Test searchByStatus: Insert 3 executions (COMPLETED, FAILED, RUNNING). GET /api/v1/search/executions?status=FAILED returns only the FAILED execution. Response has envelope: {"data":[...],"total":1,"offset":0,"limit":50} - Test searchByTimeRange: Insert executions at different times. Filter by timeFrom/timeTo returns only those in range - Test searchByDuration: Insert executions with different durations. Filter by durationMin=100&durationMax=500 returns only matching - Test searchByCorrelationId: Insert executions with different correlationIds. Filter returns only matching - Test fullTextSearchGlobal: Insert execution with error_message="NullPointerException in OrderService". Search text=NullPointerException returns it. Search text=nonexistent returns empty - Test fullTextSearchInBody: Insert execution with exchange body containing "customer-123". textInBody=customer-123 returns it - Test fullTextSearchInHeaders: Insert execution with exchange headers containing "Content-Type". textInHeaders=Content-Type returns it - Test fullTextSearchInErrors: Insert execution with error_stacktrace containing "com.example.MyException". textInErrors=MyException returns it - Test combinedFilters: status=FAILED + text=NullPointer returns only failed executions with that error - Test postAdvancedSearch: POST /api/v1/search/executions with JSON body containing all filters returns correct results - Test pagination: Insert 10 executions. Request with offset=2&limit=3 returns 3 items, total=10, offset=2 - Test emptyResults: Search with no matches returns {"data":[],"total":0,"offset":0,"limit":50} 1. Create `ClickHouseSearchEngine` in `com.cameleer.server.app.search`: - Implements SearchEngine interface from core module. - Constructor takes JdbcTemplate. - `search(SearchRequest)` method: - Build dynamic WHERE clause from non-null SearchRequest fields using ArrayList conditions and ArrayList