feat: add ACTION steps that run after the approval transaction commits
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+26
-4
@@ -25,7 +25,8 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
private static final String INSERT_DEFINITION =
|
||||
"INSERT INTO ordo_process_definition (id, name) VALUES (?, ?)";
|
||||
private static final String INSERT_STEP =
|
||||
"INSERT INTO ordo_approval_step (definition_id, step_id, step_name, policy, step_order) VALUES (?, ?, ?, ?, ?)";
|
||||
"INSERT INTO ordo_approval_step (definition_id, step_id, step_name, policy, step_order, kind, action_key)"
|
||||
+ " VALUES (?, ?, ?, ?, ?, ?, ?)";
|
||||
private static final String INSERT_CANDIDATE =
|
||||
"INSERT INTO ordo_step_candidate (definition_id, step_id, candidate, candidate_order) VALUES (?, ?, ?, ?)";
|
||||
private static final String INSERT_TRANSITION =
|
||||
@@ -41,7 +42,8 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
private static final String SELECT_DEFINITION =
|
||||
"SELECT id, name FROM ordo_process_definition WHERE id = ?";
|
||||
private static final String SELECT_STEPS =
|
||||
"SELECT step_id, step_name, policy FROM ordo_approval_step WHERE definition_id = ? ORDER BY step_order";
|
||||
"SELECT step_id, step_name, policy, kind, action_key FROM ordo_approval_step"
|
||||
+ " WHERE definition_id = ? ORDER BY step_order";
|
||||
private static final String SELECT_CANDIDATES =
|
||||
"SELECT step_id, candidate FROM ordo_step_candidate WHERE definition_id = ? ORDER BY step_id, candidate_order";
|
||||
private static final String SELECT_TRANSITIONS =
|
||||
@@ -76,9 +78,17 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
Objects.requireNonNull(definition, "definition must not be null");
|
||||
Connection connection = connectionProvider.getConnection();
|
||||
try {
|
||||
if (!insertDefinitionRow(connection, definition)) {
|
||||
// PostgreSQL aborts the current transaction on unique-constraint violations,
|
||||
// so upsert must not probe existence via a failing INSERT.
|
||||
if (definitionExists(connection, definition.id())) {
|
||||
updateDefinitionName(connection, definition);
|
||||
deleteGraph(connection, definition.id());
|
||||
} else {
|
||||
try (PreparedStatement insert = connection.prepareStatement(INSERT_DEFINITION)) {
|
||||
insert.setString(1, definition.id());
|
||||
insert.setString(2, definition.name());
|
||||
insert.executeUpdate();
|
||||
}
|
||||
}
|
||||
insertGraph(connection, definition);
|
||||
} catch (SQLException e) {
|
||||
@@ -124,7 +134,8 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
List<ApprovalStep> steps = new ArrayList<>();
|
||||
for (StepRow row : stepRows) {
|
||||
List<String> candidates = candidatesByStep.getOrDefault(row.stepId(), List.of());
|
||||
steps.add(new ApprovalStep(row.stepId(), row.stepName(), candidates, row.policy()));
|
||||
steps.add(new ApprovalStep(row.stepId(), row.stepName(), candidates, row.policy(), row.kind(),
|
||||
row.actionKey()));
|
||||
}
|
||||
List<StepTransition> transitions = new ArrayList<>();
|
||||
try (PreparedStatement selectTransitions = connection.prepareStatement(SELECT_TRANSITIONS)) {
|
||||
@@ -145,6 +156,15 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean definitionExists(Connection connection, String definitionId) throws SQLException {
|
||||
try (PreparedStatement select = connection.prepareStatement(SELECT_DEFINITION)) {
|
||||
select.setString(1, definitionId);
|
||||
try (ResultSet resultSet = select.executeQuery()) {
|
||||
return resultSet.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean insertDefinitionRow(Connection connection, ProcessDefinition definition) throws SQLException {
|
||||
try (PreparedStatement insertDefinition = connection.prepareStatement(INSERT_DEFINITION)) {
|
||||
insertDefinition.setString(1, definition.id());
|
||||
@@ -191,6 +211,8 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
insertStep.setString(3, step.name());
|
||||
insertStep.setString(4, step.policy().name());
|
||||
insertStep.setInt(5, stepOrder++);
|
||||
insertStep.setString(6, step.kind().name());
|
||||
insertStep.setString(7, step.actionKey());
|
||||
insertStep.executeUpdate();
|
||||
}
|
||||
int candidateOrder = 0;
|
||||
|
||||
+5
-2
@@ -1,6 +1,7 @@
|
||||
package com.jetlumen.ordo.storage.jdbc.mapper;
|
||||
|
||||
import com.jetlumen.ordo.api.ApprovalPolicy;
|
||||
import com.jetlumen.ordo.api.StepKind;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
@@ -16,9 +17,11 @@ public final class ApprovalStepMapper {
|
||||
|
||||
public static StepRow readRow(ResultSet resultSet) throws SQLException {
|
||||
return new StepRow(resultSet.getString("step_id"), resultSet.getString("step_name"),
|
||||
ApprovalPolicy.valueOf(resultSet.getString("policy")));
|
||||
ApprovalPolicy.valueOf(resultSet.getString("policy")),
|
||||
StepKind.valueOf(resultSet.getString("kind")),
|
||||
resultSet.getString("action_key"));
|
||||
}
|
||||
|
||||
public record StepRow(String stepId, String stepName, ApprovalPolicy policy) {
|
||||
public record StepRow(String stepId, String stepName, ApprovalPolicy policy, StepKind kind, String actionKey) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
-- Adds ACTION step kind and an optional action_key (host ActionHandler lookup).
|
||||
ALTER TABLE ordo_approval_step ADD COLUMN kind VARCHAR(16) NOT NULL DEFAULT 'APPROVAL';
|
||||
ALTER TABLE ordo_approval_step ADD COLUMN action_key VARCHAR(255);
|
||||
Reference in New Issue
Block a user