Class InMemoryFlowRepository
java.lang.Object
cloud.opencode.base.flow.persistence.memory.InMemoryFlowRepository
- All Implemented Interfaces:
FlowRepository
Thread-safe, in-memory
FlowRepository for unit tests, integration
tests, and short-lived demos. Not suitable for production: state is lost on
JVM exit and there is no cross-process coordination.
线程安全的内存版 FlowRepository,用于单测 / 集测 / 短期演示。
不适合生产:进程退出即丢数据,且无跨进程协调。
Implementation notes:
- Mutable entity tables use
ConcurrentHashMap. - Append-only history and vote lists use
CopyOnWriteArrayList(small lists, infrequent writes). updateInstance(FlowInstance)/updateTask(Task)implement optimistic locking viaConcurrentHashMap.compute(K, BiFunction): the new row is accepted only when the storedlockVersionequals the incominglockVersion; on success the stored row is replaced withlockVersion + 1.casIncrementAddsignDepth(String, int, int)usescomputeas well for a single-shot CAS that respects both the version predicate and theaddsign_depth < maxDepthpredicate.cancelOtherPendingTasks(String, String, String)iterates matching tasks and applies an optimistic-lock cancel update to each. It is best-effort with respect to concurrent writers: tasks updated between the snapshot read and the per-task CAS are simply skipped.
- Since:
- JDK 25, opencode-base-flow V1.0.5
- Author:
- Leon Soo
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intHard ceiling on the in-memory history / vote logs so a long-running test process or demo doesn't slowly OOM. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidappendHistory(HistoryRecord record) Appends a new history row.intcancelAllTasksForStep(String instanceId, String stepId) Bulk-transitions every task under(instanceId, stepId)whose current status is notTaskStatus.CANCELEDinto theTaskStatus.CANCELEDstate — including DONE / REJECTED rows from a prior approval round.intcancelOtherPendingTasks(String instanceId, String stepId, String exceptTaskId) Bulk-cancels every otherTaskStatus.PENDINGtask on the same step (excludingexceptTaskId), respecting optimistic-lock version.intcasIncrementAddsignDepth(String instanceId, int expectedVersion, int maxDepth) Compare-and-set:UPDATE addsign_depth = addsign_depth + 1, version = version + 1 WHERE id = ? AND version = ? AND addsign_depth < maxDepth.findActiveDefinition(String flowKey) Returns the singleFlowStatus.ACTIVEdefinition for the given business key, if any.Looks up a definition by its primary id.findDefinitionVersions(String flowKey) Lists every persisted version of the given business key, in version ascending order.findHistoryByInstance(String instanceId) Lists every history row for an instance in chronological order (earliest first).findHistoryByTaskId(String taskId) Looks up a history row by its related task id (one-to-one for terminal task actions such as approve / reject).findHistoryByUser(String userId, int page, int size) Paginated history query for the given user (matched onHistoryRecord.operatorId()).Looks up an instance by id.findInstancesByInitiator(String userId, int page, int size) Lists instances started by the given user, paginated.findTaskById(String id) Looks up a task by id.findTasksByInstance(String instanceId) Lists every task (any status) under the given instance.findTasksByInstanceAndStatus(String instanceId, TaskStatus status) Lists tasks that belong to the given instance and currently sit in the given status.findTodoByUser(String userId, int page, int size) Paginated todo-list query for the given user (status =TaskStatus.PENDINGonly).findVotesByTask(String taskId) Lists every vote recorded against the given task, in vote order.voidrecordVote(String taskId, String voterId, VoteOpinion opinion) Records a single vote at aStepType.VOTEstep.voidrunInTransaction(Runnable action) Serialises the action under a reentrant lock and provides snapshot rollback if the action throws.Persists a new flow definition.saveInstance(FlowInstance inst) Persists a new flow instance.Persists a new task.voidupdateDefinitionStatus(String id, FlowStatus newStatus) Mutates the lifecycle status of a definition (ACTIVE / DEPRECATED).intupdateInstance(FlowInstance inst) Optimistic-lock UPDATE; returns the number of affected rows (0indicates version conflict).intupdateTask(Task task) Optimistic-lock UPDATE; returns affected rows (0= version conflict).
-
Field Details
-
MAX_LOG_ENTRIES
public static final int MAX_LOG_ENTRIESHard ceiling on the in-memory history / vote logs so a long-running test process or demo doesn't slowly OOM. When the cap is hit the repository fails-closed instead of silently dropping rows (which would corrupt the audit invariant). 单进程内 history / vote 日志总条数上限;上限到达后 fail-closed 拒写。- See Also:
-
-
Constructor Details
-
InMemoryFlowRepository
public InMemoryFlowRepository()Constructs an empty in-memory repository. 构造一个空的内存仓储。- Since:
- JDK 25, opencode-base-flow V1.0.5
-
-
Method Details
-
saveDefinition
Description copied from interface:FlowRepositoryPersists a new flow definition. The returned record reflects the stored state (including any engine-assigned fields). 持久化一份新的流程定义。返回已存储的视图。- Specified by:
saveDefinitionin interfaceFlowRepository- Parameters:
def- the definition to persist — 待持久化的定义- Returns:
- the persisted definition — 已持久化的定义
-
findDefinitionById
Description copied from interface:FlowRepositoryLooks up a definition by its primary id. 根据主键 ID 查找定义。- Specified by:
findDefinitionByIdin interfaceFlowRepository- Parameters:
id- definition id — 定义 ID- Returns:
- the definition wrapped in an
Optional— 定义(Optional)
-
findActiveDefinition
Description copied from interface:FlowRepositoryReturns the singleFlowStatus.ACTIVEdefinition for the given business key, if any. 返回指定业务 key 当前唯一启用的(FlowStatus.ACTIVE)定义。- Specified by:
findActiveDefinitionin interfaceFlowRepository- Parameters:
flowKey- business flow key — 业务 key- Returns:
- the active definition — 启用中的定义
-
findDefinitionVersions
Description copied from interface:FlowRepositoryLists every persisted version of the given business key, in version ascending order. 返回给定业务 key 所有版本(按版本号升序)。- Specified by:
findDefinitionVersionsin interfaceFlowRepository- Parameters:
flowKey- business flow key — 业务 key- Returns:
- all definition versions — 全部版本
-
updateDefinitionStatus
Description copied from interface:FlowRepositoryMutates the lifecycle status of a definition (ACTIVE / DEPRECATED). 修改某定义的生命周期状态(ACTIVE / DEPRECATED)。- Specified by:
updateDefinitionStatusin interfaceFlowRepository- Parameters:
id- definition id — 定义 IDnewStatus- the new status — 新状态
-
saveInstance
Description copied from interface:FlowRepositoryPersists a new flow instance. 持久化新的流程实例。- Specified by:
saveInstancein interfaceFlowRepository- Parameters:
inst- the instance to persist — 待持久化的实例- Returns:
- the persisted instance — 已持久化的实例
-
findInstanceById
Description copied from interface:FlowRepositoryLooks up an instance by id. 根据 ID 查找实例。- Specified by:
findInstanceByIdin interfaceFlowRepository- Parameters:
id- instance id — 实例 ID- Returns:
- the instance wrapped in an
Optional— 实例(Optional)
-
findInstancesByInitiator
Description copied from interface:FlowRepositoryLists instances started by the given user, paginated. 分页列出指定发起人启动的实例。- Specified by:
findInstancesByInitiatorin interfaceFlowRepository- Parameters:
userId- initiator user id — 发起人 userIdpage- zero-based page index — 页码(0 起)size- page size — 每页大小- Returns:
- instances on the requested page — 该页实例
-
updateInstance
Description copied from interface:FlowRepositoryOptimistic-lock UPDATE; returns the number of affected rows (0indicates version conflict). 乐观锁 UPDATE;返回 affected rows(0表示版本冲突)。- Specified by:
updateInstancein interfaceFlowRepository- Parameters:
inst- the instance to update — 待更新的实例- Returns:
- affected rows — 影响行数
-
casIncrementAddsignDepth
Description copied from interface:FlowRepositoryCompare-and-set:UPDATE addsign_depth = addsign_depth + 1, version = version + 1 WHERE id = ? AND version = ? AND addsign_depth < maxDepth. Returns affected rows (0= conflict or depth exceeded). Callers must re-read the instance to distinguish the two cases. CAS:UPDATE addsign_depth + 1, version + 1 WHERE id = ? AND version = ? AND addsign_depth < maxDepth。返回 affected rows(0表示冲突或超深)。调用方需复读 instance 区分两种情况。- Specified by:
casIncrementAddsignDepthin interfaceFlowRepository- Parameters:
instanceId- instance id — 实例 IDexpectedVersion- expected current version — 期望的当前版本maxDepth- configured max addsign depth — 配置的加签链上限- Returns:
- affected rows — 影响行数
-
saveTask
Description copied from interface:FlowRepositoryPersists a new task. 持久化新任务。- Specified by:
saveTaskin interfaceFlowRepository- Parameters:
task- the task to persist — 待持久化的任务- Returns:
- the persisted task — 已持久化的任务
-
findTaskById
Description copied from interface:FlowRepositoryLooks up a task by id. 根据 ID 查找任务。- Specified by:
findTaskByIdin interfaceFlowRepository- Parameters:
id- task id — 任务 ID- Returns:
- the task wrapped in an
Optional— 任务(Optional)
-
findTasksByInstanceAndStatus
Description copied from interface:FlowRepositoryLists tasks that belong to the given instance and currently sit in the given status. 列出指定实例下、指定状态的任务。- Specified by:
findTasksByInstanceAndStatusin interfaceFlowRepository- Parameters:
instanceId- owning instance id — 所属实例 IDstatus- task status filter — 任务状态- Returns:
- matching tasks — 符合条件的任务
-
findTasksByInstance
Description copied from interface:FlowRepositoryLists every task (any status) under the given instance. 列出指定实例下所有任务(不限状态)。- Specified by:
findTasksByInstancein interfaceFlowRepository- Parameters:
instanceId- owning instance id — 所属实例 ID- Returns:
- all tasks — 所有任务
-
findTodoByUser
Description copied from interface:FlowRepositoryPaginated todo-list query for the given user (status =TaskStatus.PENDINGonly). 分页查询某用户的待办(仅TaskStatus.PENDING)。- Specified by:
findTodoByUserin interfaceFlowRepository- Parameters:
userId- assignee user id — 承接人 userIdpage- zero-based page index — 页码(0 起)size- page size — 每页大小- Returns:
- tasks on the requested page — 该页任务
-
updateTask
Description copied from interface:FlowRepositoryOptimistic-lock UPDATE; returns affected rows (0= version conflict). 乐观锁 UPDATE;返回 affected rows(0表示版本冲突)。- Specified by:
updateTaskin interfaceFlowRepository- Parameters:
task- the task to update — 待更新的任务- Returns:
- affected rows — 影响行数
-
cancelAllTasksForStep
Description copied from interface:FlowRepositoryBulk-transitions every task under(instanceId, stepId)whose current status is notTaskStatus.CANCELEDinto theTaskStatus.CANCELEDstate — including DONE / REJECTED rows from a prior approval round. Used byRejectOperationwhen rolling back to a previously visited step so thatStepEvaluatoronly ever observes tasks from the new batch. 批量将(instanceId, stepId)下所有非 CANCELED 状态的任务(含上一轮 的 DONE / REJECTED)置为TaskStatus.CANCELED。RejectOperation在回退到已访问节点时调用此方法,确保StepEvaluator只看见新一轮批次的任务。Invariant: each step has at most one active batch of tasks at any given time. Reject re-entry must enforce this by calling this method for every affected step before creating fresh PENDING rows.
不变式:任意时刻每个 step 最多有一批活跃 task;reject 重入前必须对所有 受影响 step 调用本方法。
- Specified by:
cancelAllTasksForStepin interfaceFlowRepository- Parameters:
instanceId- owning instance id — 所属实例 IDstepId- step id — 节点 ID- Returns:
- number of affected rows — 影响行数
-
cancelOtherPendingTasks
Description copied from interface:FlowRepositoryBulk-cancels every otherTaskStatus.PENDINGtask on the same step (excludingexceptTaskId), respecting optimistic-lock version. Returns the number of tasks that were successfully canceled. 批量取消同节点其他 PENDING 任务(不含exceptTaskId),遵守乐观锁; 返回成功取消的条数。- Specified by:
cancelOtherPendingTasksin interfaceFlowRepository- Parameters:
instanceId- owning instance id — 所属实例 IDstepId- step id — 节点 IDexceptTaskId- the task id to keep — 保留的任务 ID- Returns:
- number of canceled tasks — 成功取消条数
-
appendHistory
Description copied from interface:FlowRepositoryAppends a new history row. History is append-only — once written, rows are never updated or deleted. 追加一条历史记录。历史表仅追加,写入后不可更新或删除。- Specified by:
appendHistoryin interfaceFlowRepository- Parameters:
record- the history row to append — 待追加的历史
-
findHistoryByInstance
Description copied from interface:FlowRepositoryLists every history row for an instance in chronological order (earliest first). 按时间升序列出指定实例的所有历史记录。- Specified by:
findHistoryByInstancein interfaceFlowRepository- Parameters:
instanceId- owning instance id — 所属实例 ID- Returns:
- chronological history — 时间升序的历史
-
findHistoryByUser
Description copied from interface:FlowRepositoryPaginated history query for the given user (matched onHistoryRecord.operatorId()). 分页查询某用户的历史记录(按HistoryRecord.operatorId()匹配)。- Specified by:
findHistoryByUserin interfaceFlowRepository- Parameters:
userId- operator user id — 操作人 userIdpage- zero-based page index — 页码(0 起)size- page size — 每页大小- Returns:
- history rows on the requested page — 该页历史
-
findHistoryByTaskId
Description copied from interface:FlowRepositoryLooks up a history row by its related task id (one-to-one for terminal task actions such as approve / reject). 按关联任务 ID 查找历史(approve / reject 等终态任务动作一对一)。- Specified by:
findHistoryByTaskIdin interfaceFlowRepository- Parameters:
taskId- related task id — 关联任务 ID- Returns:
- the history row wrapped in an
Optional— 历史(Optional)
-
recordVote
Description copied from interface:FlowRepositoryRecords a single vote at aStepType.VOTEstep. Append-only. 在StepType.VOTE节点记录一票。追加写。- Specified by:
recordVotein interfaceFlowRepository- Parameters:
taskId- related task id — 关联任务 IDvoterId- voter user id — 投票人opinion- vote opinion — 投票意见
-
findVotesByTask
Description copied from interface:FlowRepositoryLists every vote recorded against the given task, in vote order. 列出关联任务的所有投票(按投票顺序)。- Specified by:
findVotesByTaskin interfaceFlowRepository- Parameters:
taskId- related task id — 关联任务 ID- Returns:
- votes in submission order — 投票(按提交顺序)
-
runInTransaction
Serialises the action under a reentrant lock and provides snapshot rollback if the action throws. Snapshot is taken on the outermostrunInTransactionentry (nested calls join the outer scope and do not re-snapshot). Mutations todefinitions,instances,tasks,historyLog,voteLogare reverted to the snapshot when the action throws, then the original exception propagates.Caveat: only mutations made via this repository are tracked. Concurrent writes from threads outside any
用可重入锁串行化动作并在抛异常时按快照回滚:仅最外层 tx 入口取快照, 嵌套调用并入外层不重复快照;动作抛异常时还原 5 张表后再向上抛出。 仅追踪经本仓储的写入;非 tx 路径上的并发写入不在隔离范围内。runInTransactioncall are not isolated; the lock only serialises tx callers.- Specified by:
runInTransactionin interfaceFlowRepository- Parameters:
action- the action to run — 待执行动作- Since:
- JDK 25, opencode-base-flow V1.0.5
-