ExecutionController was @ConditionalOnMissingBean(ChunkAccumulator.class), and ChunkAccumulator is registered unconditionally — the legacy controller never bound in any profile. Even if it had, IngestionService.ingestExecution called executionStore.upsert(), and the only ExecutionStore impl (ClickHouseExecutionStore) threw UnsupportedOperationException from upsert and upsertProcessors. The entire RouteExecution → upsert path was dead code carrying four transitive dependencies (RouteExecution import, eventPublisher wiring, body-size-limit config, searchIndexer::onExecutionUpdated hook). Removed: - cameleer-server-app/.../controller/ExecutionController.java (whole file) - ExecutionStore.upsert + upsertProcessors (interface methods) - ClickHouseExecutionStore.upsert + upsertProcessors (thrower overrides) - IngestionService.ingestExecution + toExecutionRecord + flattenProcessors + hasAnyTraceData + truncateBody + toJson/toJsonObject helpers - IngestionService constructor now takes (DiagramStore, WriteBuffer<Metrics>); dropped ExecutionStore + Consumer<ExecutionUpdatedEvent> + bodySizeLimit - StorageBeanConfig.ingestionService(...) simplified accordingly Untouched because still in use: - ExecutionRecord / ProcessorRecord records (findById / findProcessors / SearchIndexer / DetailController) - SearchIndexer (its onExecutionUpdated never fires now since no-one publishes ExecutionUpdatedEvent, but SearchIndexerStats is still referenced by ClickHouseAdminController — separate cleanup) - TaggedExecution record has no remaining callers after this change — flagged in core-classes.md as a leftover; separate cleanup. Rule docs updated: - .claude/rules/app-classes.md: retired ExecutionController bullet, fixed stale URL for ChunkIngestionController (it owns /api/v1/data/executions, not /api/v1/ingestion/chunk/executions). - .claude/rules/core-classes.md: IngestionService surface + note the dead TaggedExecution. Full IT suite post-removal: 560 tests run, 11 F + 1 E — same 12 failures in the same 3 previously-parked classes (AgentSseControllerIT / SseSigningIT SSE-timing + ClickHouseStatsStoreIT timezone bug). No regression. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9.8 KiB
9.8 KiB
paths
| paths | |
|---|---|
|
Core Module Key Classes
cameleer-server-core/src/main/java/com/cameleer/server/core/
agent/ — Agent lifecycle and commands
AgentRegistryService— in-memory registry (ConcurrentHashMap), register/heartbeat/lifecycleAgentInfo— record: id, name, application, environmentId, version, routeIds, capabilities, stateAgentCommand— record: id, type, targetAgent, payload, createdAt, expiresAtAgentEventService— records agent state changes, heartbeatsAgentState— enum: LIVE, STALE, DEAD, SHUTDOWNCommandType— enum for command types (config-update, deep-trace, replay, route-control, etc.)CommandStatus— enum for command acknowledgement statesCommandReply— record: command execution result from agentAgentEventRecord,AgentEventRepository— event persistence.AgentEventRepository.queryPage(...)is cursor-paginated (AgentEventPage{data, nextCursor, hasMore}); the legacy non-paginatedquery(...)path is gone.AgentEventRepository.findInWindow(env, appSlug, agentId, eventTypes, from, to, limit)returns matching events ordered by(timestamp ASC, insert_id ASC)— consumed byAgentLifecycleEvaluator.AgentEventPage— record:(List<AgentEventRecord> data, String nextCursor, boolean hasMore)returned byAgentEventRepository.queryPageAgentEventListener— callback interface for agent eventsRouteStateRegistry— tracks per-agent route states
runtime/ — App/Environment/Deployment domain
App— record: id, environmentId, slug, displayName, containerConfig (JSONB)AppVersion— record: id, appId, version, jarPath, detectedRuntimeType, detectedMainClassEnvironment— record: id, slug, jarRetentionCountDeployment— record: id, appId, appVersionId, environmentId, status, targetState, deploymentStrategy, replicaStates (JSONB), deployStage, containerId, containerNameDeploymentStatus— enum: STOPPED, STARTING, RUNNING, DEGRADED, STOPPING, FAILEDDeployStage— enum: PRE_FLIGHT, PULL_IMAGE, CREATE_NETWORK, START_REPLICAS, HEALTH_CHECK, SWAP_TRAFFIC, COMPLETEDeploymentService— createDeployment (deletes terminal deployments first), markRunning, markFailed, markStoppedRuntimeType— enum: AUTO, SPRING_BOOT, QUARKUS, PLAIN_JAVA, NATIVERuntimeDetector— probes JAR files at upload time: detects runtime from manifest Main-Class (Spring Boot loader, Quarkus entry point, plain Java) or native binary (non-ZIP magic bytes)ContainerRequest— record: 20 fields for Docker container creation (includes runtimeType, customArgs, mainClass)ContainerStatus— record: state, running, exitCode, errorResolvedContainerConfig— record: typed config with memoryLimitMb, memoryReserveMb, cpuRequest, cpuLimit, appPort, exposedPorts, customEnvVars, stripPathPrefix, sslOffloading, routingMode, routingDomain, serverUrl, replicas, deploymentStrategy, routeControlEnabled, replayEnabled, runtimeType, customArgs, extraNetworksRoutingMode— enum for routing strategiesConfigMerger— pure function: resolve(globalDefaults, envConfig, appConfig) -> ResolvedContainerConfigRuntimeOrchestrator— interface: startContainer, stopContainer, getContainerStatus, getLogs, startLogCapture, stopLogCaptureAppRepository,AppVersionRepository,EnvironmentRepository,DeploymentRepository— repository interfacesAppService,EnvironmentService— domain services
search/ — Execution search and stats
SearchService— search, count, stats, statsForApp, statsForRoute, timeseries, timeseriesForApp, timeseriesForRoute, timeseriesGroupedByApp, timeseriesGroupedByRoute, slaCompliance, slaCountsByApp, slaCountsByRoute, topErrors, activeErrorTypes, punchcard, distinctAttributeKeys.statsForRoute/timeseriesForRoutetake(routeId, applicationId)— app filter is applied tostats_1m_route.SearchRequest/SearchResult— search DTOsExecutionStats,ExecutionSummary— stats aggregation recordsStatsTimeseries,TopError— timeseries and error DTOsLogSearchRequest/LogSearchResponse— log search DTOs.LogSearchRequest.sources/levelsareList<String>(null-normalized, multi-value OR);cursor+limit+sortdrive keyset pagination. Response carriesnextCursor+hasMore+ per-levellevelCounts.
storage/ — Storage abstractions
ExecutionStore,MetricsStore,MetricsQueryStore,StatsStore,DiagramStore,RouteCatalogStore,SearchIndex,LogIndex— interfacesRouteCatalogEntry— record: applicationId, routeId, environment, firstSeen, lastSeenLogEntryResult— log query result recordmodel/—ExecutionDocument,MetricTimeSeries,MetricsSnapshot
rbac/ — Role-based access control
RbacService— interface: role/group CRUD, assignRoleToUser, removeRoleFromUser, addUserToGroup, removeUserFromGroup, getDirectRolesForUser, getEffectiveRolesForUser, clearManagedAssignments, assignManagedRole, addUserToManagedGroup, getStats, listUsersSystemRole— enum: AGENT, VIEWER, OPERATOR, ADMIN;normalizeScope()maps scopesUserDetail,RoleDetail,GroupDetail— recordsUserSummary,RoleSummary,GroupSummary— lightweight list recordsRbacStats— aggregate stats recordAssignmentOrigin— enum: DIRECT, CLAIM_MAPPING (tracks how roles were assigned)ClaimMappingRule— record: OIDC claim-to-role mapping ruleClaimMappingService— interface: CRUD for claim mapping rulesClaimMappingRepository— persistence interfaceRoleRepository,GroupRepository— persistence interfaces
admin/ — Server-wide admin config
SensitiveKeysConfig— record: keys (List, immutable)SensitiveKeysRepository— interface: find(), save()SensitiveKeysMerger— pure function: merge(global, perApp) -> union with case-insensitive dedup, preserves first-seen casing. Returns null when both inputs null.AppSettings,AppSettingsRepository— per-app-per-env settings config and persistence. Record carries(applicationId, environment, …); repository methods arefindByApplicationAndEnvironment,findByEnvironment,save,delete(appId, env).AppSettings.defaults(appId, env)produces a default instance scoped to an environment.ThresholdConfig,ThresholdRepository— alerting threshold config and persistenceAuditService— audit logging facadeAuditRecord,AuditResult,AuditCategory(enum:INFRA, AUTH, USER_MGMT, CONFIG, RBAC, AGENT, OUTBOUND_CONNECTION_CHANGE, OUTBOUND_HTTP_TRUST_CHANGE),AuditRepository— audit trail records and persistence
http/ — Outbound HTTP primitives (cross-cutting)
OutboundHttpClientFactory— interface:clientFor(context)returns memoizedCloseableHttpClientOutboundHttpProperties— record:trustAll, trustedCaPemPaths, defaultConnectTimeout, defaultReadTimeout, proxyUrl, proxyUsername, proxyPasswordOutboundHttpRequestContext— record of per-call TLS/timeout overrides;systemDefault()static factoryTrustMode— enum:SYSTEM_DEFAULT | TRUST_ALL | TRUST_PATHS
outbound/ — Admin-managed outbound connections
OutboundConnection— record: id, tenantId, name, description, url, method, defaultHeaders, defaultBodyTmpl, tlsTrustMode, tlsCaPemPaths, hmacSecretCiphertext, auth, allowedEnvironmentIds, createdAt, createdBy (String user_id), updatedAt, updatedBy (String user_id).isAllowedInEnvironment(envId)returns true when allowed-envs list is empty OR contains the env.OutboundAuth— sealed interface + records:None | Bearer(tokenCiphertext) | Basic(username, passwordCiphertext). Jackson@JsonTypeInfo(use = DEDUCTION)— wire shape has no discriminator, subtype inferred from fields.OutboundAuthKind,OutboundMethod— enumsOutboundConnectionRepository— CRUD by (tenantId, id): save/findById/findByName/listByTenant/deleteOutboundConnectionService— create/update/delete/get/list with uniqueness + narrow-envs + delete-if-referenced guards.rulesReferencing(id)stubbed in Plan 01 (returns[]); populated in Plan 02 againstAlertRuleRepository.
security/ — Auth
JwtService— interface: createAccessToken, createRefreshToken, validateAccessToken, validateRefreshTokenEd25519SigningService— interface: sign, getPublicKeyBase64 (config signing)OidcConfig— record: enabled, issuerUri, clientId, clientSecret, rolesClaim, defaultRoles, autoSignup, displayNameClaim, userIdClaim, audience, additionalScopesOidcConfigRepository— persistence interfacePasswordPolicyValidator— min 12 chars, 3-of-4 character classes, no username matchUserInfo,UserRepository— user identity records and persistenceInvalidTokenException— thrown on revoked/expired tokens
ingestion/ — Buffered data pipeline
IngestionService— diagram + metrics facade (ingestDiagram,acceptMetrics,getMetricsBuffer). Execution ingestion went through here via the legacyRouteExecutionshape untilChunkAccumulatortook over writes from the chunked pipeline — theingestExecutionpath plus itsExecutionStore.upsert/upsertProcessorsdependencies were removed.ChunkAccumulator— batches data for efficient flush; owns the execution write path (chunks → buffers → flush scheduler →ClickHouseExecutionStore.insertExecutionBatch).WriteBuffer— bounded ring buffer for async flushBufferedLogEntry— log entry wrapper with metadataMergedExecution,TaggedDiagram— tagged ingestion records.TaggedDiagramcarries(instanceId, applicationId, environment, graph)— env is resolved from the agent registry in the controller and stamped on the ClickHouseroute_diagramsrow. (TaggedExecutionstill lives in the package as a leftover but has no callers since the legacy PG ingest path was retired.)