feat: replace process definition graphs when no instance is running
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+99
-40
@@ -30,6 +30,14 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
"INSERT INTO ordo_step_candidate (definition_id, step_id, candidate, candidate_order) VALUES (?, ?, ?, ?)";
|
||||
private static final String INSERT_TRANSITION =
|
||||
"INSERT INTO ordo_step_transition (definition_id, from_step_id, to_step_id, condition_key, priority) VALUES (?, ?, ?, ?, ?)";
|
||||
private static final String UPDATE_DEFINITION_NAME =
|
||||
"UPDATE ordo_process_definition SET name = ? WHERE id = ?";
|
||||
private static final String DELETE_TRANSITIONS =
|
||||
"DELETE FROM ordo_step_transition WHERE definition_id = ?";
|
||||
private static final String DELETE_CANDIDATES =
|
||||
"DELETE FROM ordo_step_candidate WHERE definition_id = ?";
|
||||
private static final String DELETE_STEPS =
|
||||
"DELETE FROM ordo_approval_step WHERE definition_id = ?";
|
||||
private static final String SELECT_DEFINITION =
|
||||
"SELECT id, name FROM ordo_process_definition WHERE id = ?";
|
||||
private static final String SELECT_STEPS =
|
||||
@@ -51,47 +59,10 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
Objects.requireNonNull(definition, "definition must not be null");
|
||||
Connection connection = connectionProvider.getConnection();
|
||||
try {
|
||||
try (PreparedStatement insertDefinition = connection.prepareStatement(INSERT_DEFINITION)) {
|
||||
insertDefinition.setString(1, definition.id());
|
||||
insertDefinition.setString(2, definition.name());
|
||||
insertDefinition.executeUpdate();
|
||||
} catch (SQLException e) {
|
||||
if (isDuplicateKey(e)) {
|
||||
return false;
|
||||
}
|
||||
throw new JdbcStorageException("failed to insert definition: " + definition.id(), e);
|
||||
}
|
||||
int stepOrder = 0;
|
||||
for (ApprovalStep step : definition.steps()) {
|
||||
try (PreparedStatement insertStep = connection.prepareStatement(INSERT_STEP)) {
|
||||
insertStep.setString(1, definition.id());
|
||||
insertStep.setString(2, step.id());
|
||||
insertStep.setString(3, step.name());
|
||||
insertStep.setString(4, step.policy().name());
|
||||
insertStep.setInt(5, stepOrder++);
|
||||
insertStep.executeUpdate();
|
||||
}
|
||||
int candidateOrder = 0;
|
||||
for (String candidate : step.candidates()) {
|
||||
try (PreparedStatement insertCandidate = connection.prepareStatement(INSERT_CANDIDATE)) {
|
||||
insertCandidate.setString(1, definition.id());
|
||||
insertCandidate.setString(2, step.id());
|
||||
insertCandidate.setString(3, candidate);
|
||||
insertCandidate.setInt(4, candidateOrder++);
|
||||
insertCandidate.executeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (StepTransition transition : definition.transitions()) {
|
||||
try (PreparedStatement insertTransition = connection.prepareStatement(INSERT_TRANSITION)) {
|
||||
insertTransition.setString(1, definition.id());
|
||||
insertTransition.setString(2, transition.fromStepId());
|
||||
insertTransition.setString(3, transition.toStepId());
|
||||
insertTransition.setString(4, transition.conditionKey());
|
||||
insertTransition.setInt(5, transition.priority());
|
||||
insertTransition.executeUpdate();
|
||||
}
|
||||
if (!insertDefinitionRow(connection, definition)) {
|
||||
return false;
|
||||
}
|
||||
insertGraph(connection, definition);
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
throw new JdbcStorageException("failed to insert definition: " + definition.id(), e);
|
||||
@@ -100,6 +71,23 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void upsert(ProcessDefinition definition) {
|
||||
Objects.requireNonNull(definition, "definition must not be null");
|
||||
Connection connection = connectionProvider.getConnection();
|
||||
try {
|
||||
if (!insertDefinitionRow(connection, definition)) {
|
||||
updateDefinitionName(connection, definition);
|
||||
deleteGraph(connection, definition.id());
|
||||
}
|
||||
insertGraph(connection, definition);
|
||||
} catch (SQLException e) {
|
||||
throw new JdbcStorageException("failed to upsert definition: " + definition.id(), e);
|
||||
} finally {
|
||||
connectionProvider.close(connection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProcessDefinition> findById(String definitionId) {
|
||||
Connection connection = connectionProvider.getConnection();
|
||||
@@ -157,6 +145,77 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean insertDefinitionRow(Connection connection, ProcessDefinition definition) throws SQLException {
|
||||
try (PreparedStatement insertDefinition = connection.prepareStatement(INSERT_DEFINITION)) {
|
||||
insertDefinition.setString(1, definition.id());
|
||||
insertDefinition.setString(2, definition.name());
|
||||
insertDefinition.executeUpdate();
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
if (isDuplicateKey(e)) {
|
||||
return false;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateDefinitionName(Connection connection, ProcessDefinition definition) throws SQLException {
|
||||
try (PreparedStatement update = connection.prepareStatement(UPDATE_DEFINITION_NAME)) {
|
||||
update.setString(1, definition.name());
|
||||
update.setString(2, definition.id());
|
||||
update.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteGraph(Connection connection, String definitionId) throws SQLException {
|
||||
try (PreparedStatement deleteTransitions = connection.prepareStatement(DELETE_TRANSITIONS)) {
|
||||
deleteTransitions.setString(1, definitionId);
|
||||
deleteTransitions.executeUpdate();
|
||||
}
|
||||
try (PreparedStatement deleteCandidates = connection.prepareStatement(DELETE_CANDIDATES)) {
|
||||
deleteCandidates.setString(1, definitionId);
|
||||
deleteCandidates.executeUpdate();
|
||||
}
|
||||
try (PreparedStatement deleteSteps = connection.prepareStatement(DELETE_STEPS)) {
|
||||
deleteSteps.setString(1, definitionId);
|
||||
deleteSteps.executeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
private static void insertGraph(Connection connection, ProcessDefinition definition) throws SQLException {
|
||||
int stepOrder = 0;
|
||||
for (ApprovalStep step : definition.steps()) {
|
||||
try (PreparedStatement insertStep = connection.prepareStatement(INSERT_STEP)) {
|
||||
insertStep.setString(1, definition.id());
|
||||
insertStep.setString(2, step.id());
|
||||
insertStep.setString(3, step.name());
|
||||
insertStep.setString(4, step.policy().name());
|
||||
insertStep.setInt(5, stepOrder++);
|
||||
insertStep.executeUpdate();
|
||||
}
|
||||
int candidateOrder = 0;
|
||||
for (String candidate : step.candidates()) {
|
||||
try (PreparedStatement insertCandidate = connection.prepareStatement(INSERT_CANDIDATE)) {
|
||||
insertCandidate.setString(1, definition.id());
|
||||
insertCandidate.setString(2, step.id());
|
||||
insertCandidate.setString(3, candidate);
|
||||
insertCandidate.setInt(4, candidateOrder++);
|
||||
insertCandidate.executeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (StepTransition transition : definition.transitions()) {
|
||||
try (PreparedStatement insertTransition = connection.prepareStatement(INSERT_TRANSITION)) {
|
||||
insertTransition.setString(1, definition.id());
|
||||
insertTransition.setString(2, transition.fromStepId());
|
||||
insertTransition.setString(3, transition.toStepId());
|
||||
insertTransition.setString(4, transition.conditionKey());
|
||||
insertTransition.setInt(5, transition.priority());
|
||||
insertTransition.executeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDuplicateKey(SQLException e) {
|
||||
return "23505".equals(e.getSQLState());
|
||||
}
|
||||
|
||||
+19
@@ -1,6 +1,7 @@
|
||||
package com.jetlumen.ordo.storage.jdbc;
|
||||
|
||||
import com.jetlumen.ordo.api.ProcessInstance;
|
||||
import com.jetlumen.ordo.api.ProcessStatus;
|
||||
import com.jetlumen.ordo.api.repository.ProcessInstanceRepository;
|
||||
import com.jetlumen.ordo.storage.jdbc.mapper.ProcessInstanceMapper;
|
||||
|
||||
@@ -21,6 +22,8 @@ public final class JdbcProcessInstanceRepository implements ProcessInstanceRepos
|
||||
private static final String SELECT_INSTANCE =
|
||||
"SELECT id, definition_id, initiator, status, context_json, started_at, finished_at"
|
||||
+ " FROM ordo_process_instance WHERE id = ?";
|
||||
private static final String EXISTS_RUNNING =
|
||||
"SELECT 1 FROM ordo_process_instance WHERE definition_id = ? AND status = ? LIMIT 1";
|
||||
|
||||
private final JdbcConnectionProvider connectionProvider;
|
||||
|
||||
@@ -72,4 +75,20 @@ public final class JdbcProcessInstanceRepository implements ProcessInstanceRepos
|
||||
connectionProvider.close(connection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsRunning(String definitionId) {
|
||||
Connection connection = connectionProvider.getConnection();
|
||||
try (PreparedStatement select = connection.prepareStatement(EXISTS_RUNNING)) {
|
||||
select.setString(1, definitionId);
|
||||
select.setString(2, ProcessStatus.RUNNING.name());
|
||||
try (ResultSet resultSet = select.executeQuery()) {
|
||||
return resultSet.next();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new JdbcStorageException("failed to check running instances for definition: " + definitionId, e);
|
||||
} finally {
|
||||
connectionProvider.close(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user