feat: update PostgresDeploymentRepository for orchestration columns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-08 20:16:57 +02:00
parent 6eff271238
commit fef0239b1d
2 changed files with 61 additions and 8 deletions

View File

@@ -44,8 +44,8 @@ public class RuntimeBeanConfig {
} }
@Bean @Bean
public DeploymentRepository deploymentRepository(JdbcTemplate jdbc) { public DeploymentRepository deploymentRepository(JdbcTemplate jdbc, ObjectMapper objectMapper) {
return new PostgresDeploymentRepository(jdbc); return new PostgresDeploymentRepository(jdbc, objectMapper);
} }
@Bean @Bean

View File

@@ -3,6 +3,8 @@ package com.cameleer3.server.app.storage;
import com.cameleer3.server.core.runtime.Deployment; import com.cameleer3.server.core.runtime.Deployment;
import com.cameleer3.server.core.runtime.DeploymentRepository; import com.cameleer3.server.core.runtime.DeploymentRepository;
import com.cameleer3.server.core.runtime.DeploymentStatus; import com.cameleer3.server.core.runtime.DeploymentStatus;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.ResultSet; import java.sql.ResultSet;
@@ -10,35 +12,43 @@ import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class PostgresDeploymentRepository implements DeploymentRepository { public class PostgresDeploymentRepository implements DeploymentRepository {
private final JdbcTemplate jdbc; private static final String SELECT_COLS =
"id, app_id, app_version_id, environment_id, status, target_state, deployment_strategy, " +
"replica_states, deploy_stage, container_id, container_name, error_message, " +
"deployed_at, stopped_at, created_at";
public PostgresDeploymentRepository(JdbcTemplate jdbc) { private final JdbcTemplate jdbc;
private final ObjectMapper objectMapper;
public PostgresDeploymentRepository(JdbcTemplate jdbc, ObjectMapper objectMapper) {
this.jdbc = jdbc; this.jdbc = jdbc;
this.objectMapper = objectMapper;
} }
@Override @Override
public List<Deployment> findByAppId(UUID appId) { public List<Deployment> findByAppId(UUID appId) {
return jdbc.query( return jdbc.query(
"SELECT id, app_id, app_version_id, environment_id, status, container_id, container_name, error_message, deployed_at, stopped_at, created_at FROM deployments WHERE app_id = ? ORDER BY created_at DESC", "SELECT " + SELECT_COLS + " FROM deployments WHERE app_id = ? ORDER BY created_at DESC",
(rs, rowNum) -> mapRow(rs), appId); (rs, rowNum) -> mapRow(rs), appId);
} }
@Override @Override
public List<Deployment> findByEnvironmentId(UUID environmentId) { public List<Deployment> findByEnvironmentId(UUID environmentId) {
return jdbc.query( return jdbc.query(
"SELECT id, app_id, app_version_id, environment_id, status, container_id, container_name, error_message, deployed_at, stopped_at, created_at FROM deployments WHERE environment_id = ? ORDER BY created_at DESC", "SELECT " + SELECT_COLS + " FROM deployments WHERE environment_id = ? ORDER BY created_at DESC",
(rs, rowNum) -> mapRow(rs), environmentId); (rs, rowNum) -> mapRow(rs), environmentId);
} }
@Override @Override
public Optional<Deployment> findById(UUID id) { public Optional<Deployment> findById(UUID id) {
var results = jdbc.query( var results = jdbc.query(
"SELECT id, app_id, app_version_id, environment_id, status, container_id, container_name, error_message, deployed_at, stopped_at, created_at FROM deployments WHERE id = ?", "SELECT " + SELECT_COLS + " FROM deployments WHERE id = ?",
(rs, rowNum) -> mapRow(rs), id); (rs, rowNum) -> mapRow(rs), id);
return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0)); return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0));
} }
@@ -46,7 +56,8 @@ public class PostgresDeploymentRepository implements DeploymentRepository {
@Override @Override
public Optional<Deployment> findActiveByAppIdAndEnvironmentId(UUID appId, UUID environmentId) { public Optional<Deployment> findActiveByAppIdAndEnvironmentId(UUID appId, UUID environmentId) {
var results = jdbc.query( var results = jdbc.query(
"SELECT id, app_id, app_version_id, environment_id, status, container_id, container_name, error_message, deployed_at, stopped_at, created_at FROM deployments WHERE app_id = ? AND environment_id = ? AND status IN ('STARTING', 'RUNNING') ORDER BY created_at DESC LIMIT 1", "SELECT " + SELECT_COLS + " FROM deployments WHERE app_id = ? AND environment_id = ? " +
"AND status IN ('STARTING', 'RUNNING', 'DEGRADED') ORDER BY created_at DESC LIMIT 1",
(rs, rowNum) -> mapRow(rs), appId, environmentId); (rs, rowNum) -> mapRow(rs), appId, environmentId);
return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0)); return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0));
} }
@@ -75,15 +86,57 @@ public class PostgresDeploymentRepository implements DeploymentRepository {
jdbc.update("UPDATE deployments SET stopped_at = now() WHERE id = ?", id); jdbc.update("UPDATE deployments SET stopped_at = now() WHERE id = ?", id);
} }
public void updateReplicaStates(UUID id, List<Map<String, Object>> replicaStates) {
try {
String json = objectMapper.writeValueAsString(replicaStates);
jdbc.update("UPDATE deployments SET replica_states = ?::jsonb WHERE id = ?", json, id);
} catch (Exception e) {
throw new RuntimeException("Failed to serialize replicaStates", e);
}
}
public void updateDeployStage(UUID id, String stage) {
jdbc.update("UPDATE deployments SET deploy_stage = ? WHERE id = ?", stage, id);
}
public void updateTargetState(UUID id, String targetState) {
jdbc.update("UPDATE deployments SET target_state = ? WHERE id = ?", targetState, id);
}
public void updateDeploymentStrategy(UUID id, String strategy) {
jdbc.update("UPDATE deployments SET deployment_strategy = ? WHERE id = ?", strategy, id);
}
public Optional<Deployment> findByContainerId(String containerId) {
var results = jdbc.query(
"SELECT " + SELECT_COLS + " FROM deployments WHERE replica_states::text LIKE ? " +
"AND status IN ('STARTING', 'RUNNING', 'DEGRADED') ORDER BY created_at DESC LIMIT 1",
(rs, rowNum) -> mapRow(rs), "%" + containerId + "%");
return results.isEmpty() ? Optional.empty() : Optional.of(results.get(0));
}
private Deployment mapRow(ResultSet rs) throws SQLException { private Deployment mapRow(ResultSet rs) throws SQLException {
Timestamp deployedAt = rs.getTimestamp("deployed_at"); Timestamp deployedAt = rs.getTimestamp("deployed_at");
Timestamp stoppedAt = rs.getTimestamp("stopped_at"); Timestamp stoppedAt = rs.getTimestamp("stopped_at");
String replicaStatesJson = rs.getString("replica_states");
List<Map<String, Object>> replicaStates = null;
if (replicaStatesJson != null) {
try {
replicaStates = objectMapper.readValue(replicaStatesJson, new TypeReference<>() {});
} catch (Exception e) {
throw new SQLException("Failed to deserialize replica_states", e);
}
}
return new Deployment( return new Deployment(
UUID.fromString(rs.getString("id")), UUID.fromString(rs.getString("id")),
UUID.fromString(rs.getString("app_id")), UUID.fromString(rs.getString("app_id")),
UUID.fromString(rs.getString("app_version_id")), UUID.fromString(rs.getString("app_version_id")),
UUID.fromString(rs.getString("environment_id")), UUID.fromString(rs.getString("environment_id")),
DeploymentStatus.valueOf(rs.getString("status")), DeploymentStatus.valueOf(rs.getString("status")),
rs.getString("target_state"),
rs.getString("deployment_strategy"),
replicaStates,
rs.getString("deploy_stage"),
rs.getString("container_id"), rs.getString("container_id"),
rs.getString("container_name"), rs.getString("container_name"),
rs.getString("error_message"), rs.getString("error_message"),