runtime(deploy): capture config snapshot on RUNNING transition

Injects PostgresApplicationConfigRepository into DeploymentExecutor and
calls saveDeployedConfigSnapshot at the COMPLETE stage, before
markRunning. Snapshot contains jarVersionId, agentConfig (nullable),
and app.containerConfig. The FAILED catch path is left untouched so
snapshot stays null on failure. Verified by DeploymentSnapshotIT.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-22 21:51:00 +02:00
parent 9b851c4622
commit a79eafeaf4
2 changed files with 249 additions and 1 deletions

View File

@@ -1,6 +1,8 @@
package com.cameleer.server.app.runtime;
import com.cameleer.common.model.ApplicationConfig;
import com.cameleer.server.app.metrics.ServerMetrics;
import com.cameleer.server.app.storage.PostgresApplicationConfigRepository;
import com.cameleer.server.app.storage.PostgresDeploymentRepository;
import com.cameleer.server.core.runtime.*;
import org.slf4j.Logger;
@@ -25,6 +27,7 @@ public class DeploymentExecutor {
private final EnvironmentService envService;
private final DeploymentRepository deploymentRepository;
private final PostgresDeploymentRepository pgDeployRepo;
private final PostgresApplicationConfigRepository applicationConfigRepository;
@Autowired(required = false)
private DockerNetworkManager networkManager;
@@ -75,13 +78,15 @@ public class DeploymentExecutor {
DeploymentService deploymentService,
AppService appService,
EnvironmentService envService,
DeploymentRepository deploymentRepository) {
DeploymentRepository deploymentRepository,
PostgresApplicationConfigRepository applicationConfigRepository) {
this.orchestrator = orchestrator;
this.deploymentService = deploymentService;
this.appService = appService;
this.envService = envService;
this.deploymentRepository = deploymentRepository;
this.pgDeployRepo = (PostgresDeploymentRepository) deploymentRepository;
this.applicationConfigRepository = applicationConfigRepository;
}
@Async("deploymentTaskExecutor")
@@ -252,6 +257,17 @@ public class DeploymentExecutor {
// === COMPLETE ===
updateStage(deployment.id(), DeployStage.COMPLETE);
// Capture config snapshot before marking RUNNING
ApplicationConfig agentConfig = applicationConfigRepository
.findByApplicationAndEnvironment(app.slug(), env.slug())
.orElse(null);
DeploymentConfigSnapshot snapshot = new DeploymentConfigSnapshot(
deployment.appVersionId(),
agentConfig,
app.containerConfig()
);
pgDeployRepo.saveDeployedConfigSnapshot(deployment.id(), snapshot);
String primaryContainerId = newContainerIds.get(0);
DeploymentStatus finalStatus = healthyCount == config.replicas()
? DeploymentStatus.RUNNING : DeploymentStatus.DEGRADED;