feat: migrate UI to @cameleer/design-system, add backend endpoints
Backend: - Add agent_events table (V5) and lifecycle event recording - Add route catalog endpoint (GET /routes/catalog) - Add route metrics endpoint (GET /routes/metrics) - Add agent events endpoint (GET /agents/events-log) - Enrich AgentInstanceResponse with tps, errorRate, activeRoutes, uptimeSeconds - Add TimescaleDB retention/compression policies (V6) Frontend: - Replace custom Mission Control UI with @cameleer/design-system components - Rebuild all pages: Dashboard, ExchangeDetail, RoutesMetrics, AgentHealth, AgentInstance, RBAC, AuditLog, OIDC, DatabaseAdmin, OpenSearchAdmin, Swagger - New LayoutShell with design system AppShell, Sidebar, TopBar, CommandPalette - Consume design system from Gitea npm registry (@cameleer/design-system@0.0.1) - Add .npmrc for scoped registry, update Dockerfile with REGISTRY_TOKEN arg CI: - Pass REGISTRY_TOKEN build-arg to UI Docker build step Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,17 +1,23 @@
|
||||
package com.cameleer3.server.app.agent;
|
||||
|
||||
import com.cameleer3.server.core.agent.AgentEventService;
|
||||
import com.cameleer3.server.core.agent.AgentInfo;
|
||||
import com.cameleer3.server.core.agent.AgentRegistryService;
|
||||
import com.cameleer3.server.core.agent.AgentState;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Periodic task that checks agent lifecycle and expires old commands.
|
||||
* <p>
|
||||
* Runs on a configurable fixed delay (default 10 seconds). Transitions
|
||||
* agents LIVE -> STALE -> DEAD based on heartbeat timing, and removes
|
||||
* expired pending commands.
|
||||
* expired pending commands. Records lifecycle events for state transitions.
|
||||
*/
|
||||
@Component
|
||||
public class AgentLifecycleMonitor {
|
||||
@@ -19,18 +25,46 @@ public class AgentLifecycleMonitor {
|
||||
private static final Logger log = LoggerFactory.getLogger(AgentLifecycleMonitor.class);
|
||||
|
||||
private final AgentRegistryService registryService;
|
||||
private final AgentEventService agentEventService;
|
||||
|
||||
public AgentLifecycleMonitor(AgentRegistryService registryService) {
|
||||
public AgentLifecycleMonitor(AgentRegistryService registryService,
|
||||
AgentEventService agentEventService) {
|
||||
this.registryService = registryService;
|
||||
this.agentEventService = agentEventService;
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelayString = "${agent-registry.lifecycle-check-interval-ms:10000}")
|
||||
public void checkLifecycle() {
|
||||
try {
|
||||
// Snapshot states before lifecycle check
|
||||
Map<String, AgentState> statesBefore = new HashMap<>();
|
||||
for (AgentInfo agent : registryService.findAll()) {
|
||||
statesBefore.put(agent.id(), agent.state());
|
||||
}
|
||||
|
||||
registryService.checkLifecycle();
|
||||
registryService.expireOldCommands();
|
||||
|
||||
// Detect transitions and record events
|
||||
for (AgentInfo agent : registryService.findAll()) {
|
||||
AgentState before = statesBefore.get(agent.id());
|
||||
if (before != null && before != agent.state()) {
|
||||
String eventType = mapTransitionEvent(before, agent.state());
|
||||
if (eventType != null) {
|
||||
agentEventService.recordEvent(agent.id(), agent.group(), eventType,
|
||||
agent.name() + " " + before + " -> " + agent.state());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error during agent lifecycle check", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String mapTransitionEvent(AgentState from, AgentState to) {
|
||||
if (from == AgentState.LIVE && to == AgentState.STALE) return "WENT_STALE";
|
||||
if (from == AgentState.STALE && to == AgentState.DEAD) return "WENT_DEAD";
|
||||
if (from == AgentState.STALE && to == AgentState.LIVE) return "RECOVERED";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user