feat: add explicit conditional routing for approval steps
Require ProcessDefinition transitions so the engine can branch or end by conditionKey, persist them in JDBC, and pin repository text files to LF. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+30
-1
@@ -2,9 +2,12 @@ package com.jetlumen.ordo.storage.jdbc;
|
||||
|
||||
import com.jetlumen.ordo.api.ApprovalStep;
|
||||
import com.jetlumen.ordo.api.ProcessDefinition;
|
||||
import com.jetlumen.ordo.api.StepTransition;
|
||||
import com.jetlumen.ordo.api.repository.ProcessDefinitionRepository;
|
||||
import com.jetlumen.ordo.storage.jdbc.mapper.ApprovalStepMapper;
|
||||
import com.jetlumen.ordo.storage.jdbc.mapper.ApprovalStepMapper.StepRow;
|
||||
import com.jetlumen.ordo.storage.jdbc.mapper.StepTransitionMapper;
|
||||
import com.jetlumen.ordo.storage.jdbc.mapper.StepTransitionMapper.TransitionRow;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
@@ -25,12 +28,17 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
"INSERT INTO ordo_approval_step (definition_id, step_id, step_name, policy, step_order) 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 =
|
||||
"INSERT INTO ordo_step_transition (definition_id, from_step_id, to_step_id, condition_key, priority) VALUES (?, ?, ?, ?, ?)";
|
||||
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";
|
||||
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 =
|
||||
"SELECT from_step_id, to_step_id, condition_key, priority FROM ordo_step_transition "
|
||||
+ "WHERE definition_id = ? ORDER BY from_step_id, priority";
|
||||
|
||||
private final JdbcConnectionProvider connectionProvider;
|
||||
|
||||
@@ -74,6 +82,16 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
throw new JdbcStorageException("failed to insert definition: " + definition.id(), e);
|
||||
@@ -120,7 +138,18 @@ public final class JdbcProcessDefinitionRepository implements ProcessDefinitionR
|
||||
List<String> candidates = candidatesByStep.getOrDefault(row.stepId(), List.of());
|
||||
steps.add(new ApprovalStep(row.stepId(), row.stepName(), candidates, row.policy()));
|
||||
}
|
||||
return Optional.of(new ProcessDefinition(definitionId, name, steps));
|
||||
List<StepTransition> transitions = new ArrayList<>();
|
||||
try (PreparedStatement selectTransitions = connection.prepareStatement(SELECT_TRANSITIONS)) {
|
||||
selectTransitions.setString(1, definitionId);
|
||||
try (ResultSet resultSet = selectTransitions.executeQuery()) {
|
||||
while (resultSet.next()) {
|
||||
TransitionRow row = StepTransitionMapper.readRow(resultSet);
|
||||
transitions.add(new StepTransition(row.fromStepId(), row.toStepId(), row.conditionKey(),
|
||||
row.priority()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.of(new ProcessDefinition(definitionId, name, steps, transitions));
|
||||
} catch (SQLException e) {
|
||||
throw new JdbcStorageException("failed to load definition: " + definitionId, e);
|
||||
} finally {
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.jetlumen.ordo.storage.jdbc.mapper;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/** Maps rows of {@code ordo_step_transition}. */
|
||||
public final class StepTransitionMapper {
|
||||
private StepTransitionMapper() {
|
||||
}
|
||||
|
||||
public static TransitionRow readRow(ResultSet resultSet) throws SQLException {
|
||||
return new TransitionRow(
|
||||
resultSet.getString("from_step_id"),
|
||||
resultSet.getString("to_step_id"),
|
||||
resultSet.getString("condition_key"),
|
||||
resultSet.getInt("priority"));
|
||||
}
|
||||
|
||||
public record TransitionRow(String fromStepId, String toStepId, String conditionKey, int priority) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE ordo_step_transition (
|
||||
definition_id VARCHAR(64) NOT NULL,
|
||||
from_step_id VARCHAR(64) NOT NULL,
|
||||
to_step_id VARCHAR(64),
|
||||
condition_key VARCHAR(255),
|
||||
priority INTEGER NOT NULL,
|
||||
PRIMARY KEY (definition_id, from_step_id, priority),
|
||||
CONSTRAINT fk_transition_from FOREIGN KEY (definition_id, from_step_id)
|
||||
REFERENCES ordo_approval_step (definition_id, step_id),
|
||||
CONSTRAINT fk_transition_to FOREIGN KEY (definition_id, to_step_id)
|
||||
REFERENCES ordo_approval_step (definition_id, step_id)
|
||||
);
|
||||
Reference in New Issue
Block a user