feat: let the current assignee reassign a pending task

Keep the same task id, move the pending inbox, and record TASK_REASSIGNED without advancing the step.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
0264408
2026-09-16 08:40:25 +08:00
co-authored by Cursor
parent 5795778112
commit 850583f326
15 changed files with 286 additions and 26 deletions
@@ -27,7 +27,9 @@ public final class JdbcApprovalTaskRepository implements ApprovalTaskRepository
+ " VALUES (?, ?, ?, ?, ?, ?, ?)";
private static final String COMPLETE_IF_PENDING =
"UPDATE ordo_approval_task SET status = ?, completed_at = ?, action_actor = ?, action_comment = ?, action_at = ?"
+ " WHERE id = ? AND status = 'PENDING'";
+ " WHERE id = ? AND status = 'PENDING' AND assignee = ?";
private static final String REASSIGN_IF_PENDING =
"UPDATE ordo_approval_task SET assignee = ? WHERE id = ? AND status = 'PENDING' AND assignee = ?";
private static final String SELECT_TASK =
"SELECT " + TASK_COLUMNS + " FROM ordo_approval_task WHERE id = ?";
private static final String SELECT_BY_INSTANCE =
@@ -119,6 +121,24 @@ public final class JdbcApprovalTaskRepository implements ApprovalTaskRepository
}
}
@Override
public boolean reassignIfPending(String taskId, String expectedAssignee, String newAssignee) {
Objects.requireNonNull(taskId, "taskId must not be null");
Objects.requireNonNull(expectedAssignee, "expectedAssignee must not be null");
Objects.requireNonNull(newAssignee, "newAssignee must not be null");
Connection connection = connectionProvider.getConnection();
try (PreparedStatement update = connection.prepareStatement(REASSIGN_IF_PENDING)) {
update.setString(1, newAssignee);
update.setString(2, taskId);
update.setString(3, expectedAssignee);
return update.executeUpdate() == 1;
} catch (SQLException e) {
throw new JdbcStorageException("failed to reassign task: " + taskId, e);
} finally {
connectionProvider.close(connection);
}
}
@Override
public Page<ApprovalTask> query(TaskQuery query, PageRequest pageRequest) {
Objects.requireNonNull(query, "query must not be null");
@@ -40,6 +40,7 @@ public final class ApprovalTaskMapper {
statement.setTimestamp(5, Timestamp.from(action.operatedAt()));
}
statement.setString(6, completedTask.id());
statement.setString(7, completedTask.assignee());
}
public static ApprovalTask read(ResultSet resultSet) throws SQLException {