release: FL 2.0 候选(C01 记账边界+P2-2 认领协议+D10 变量契约+D11 资格终审+D09 激活代次+T01/T03/T04/T05)
按《FL最终代码审计与上线阻断清单》194 项已审计工作树形成候选,基座 = origin/main 11e0778。
- 源码/测试/资源:沿用已审计工作树内容(96 项相对远端为新增或更新),含未跟踪实现
CallbackFactStore、CallbackSourcePolicy、VariableContract、FormalApplyCommandService、
FlowActorContextGate 等;C01 续验夹具修正一并入内。
- CI:保留远端 11e0778 的门禁强化(CI_SOURCE_SHA 核对、容器回收验证、空 schema 反向门禁、
main ref 才推镜像);ci/flow-test-schema.sql 按当前实体重新生成(14→20 表,补 6 新表与
6 新列,回调日志复合唯一键 uk_flw_log_event_reg),workflow 表数断言同步 14→20。
- 依据:docs/tasks/evidence/FL-final-audit-20261027(194 项哈希/版本核对)。
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
package com.yunhai.flowcenter.entity;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 待推进意图(2026-10-25 T05):任务办理事务内持久化"这个节点该继续推进了"的事实,
|
||||
* 事务外 worker 领取执行——办理事务提交成功 ⇔ 推进意图已持久化,进程崩溃/重启后
|
||||
* 扫描续跑(旧链路 AFTER_COMMIT 三次内存重试,耗尽只 log.error,重启即丢)。
|
||||
*
|
||||
* <p>D09:每个激活批次记录精确任务成员,未办理时以 DONE 等待;办理同事务串行刷新
|
||||
* 本批次的末笔任务及 PENDING 工作。worker 按 id+revision 锁定当前读,推进与结算同事务;
|
||||
* NULL 代次只允许明确接棒或留待有证据的人工回填,不作为本代放行。</p>
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "flw_advance_intent",
|
||||
uniqueConstraints = @UniqueConstraint(name = "uk_flw_advance_activation", columnNames = "activation_task_id"),
|
||||
indexes = {
|
||||
@Index(name = "idx_flw_advance_intent_due", columnList = "status, next_retry_at"),
|
||||
@Index(name = "idx_flw_advance_intent_instance", columnList = "instance_id")})
|
||||
public class FlwAdvanceIntent extends BaseEntity {
|
||||
|
||||
public static final String STATE_PENDING = "PENDING";
|
||||
public static final String STATE_DONE = "DONE";
|
||||
public static final String STATE_EXHAUSTED = "EXHAUSTED";
|
||||
|
||||
@Column(name = "instance_id", nullable = false)
|
||||
private Long instanceId;
|
||||
|
||||
/** 触发推进的节点(TASK_HANDLED 的 nodeId) */
|
||||
@Column(name = "node_id", nullable = false, length = 64)
|
||||
private String nodeId;
|
||||
|
||||
/** First task CREATED in this activation batch; never the last task to finish. NULL = unanchored legacy work. */
|
||||
@Column(name = "activation_task_id")
|
||||
private Long activationTaskId;
|
||||
|
||||
/** Exact membership, including transfers; comma-delimited positive task IDs, e.g. ,12,14,. */
|
||||
@Column(name = "activation_task_ids", columnDefinition = "LONGTEXT")
|
||||
private String activationTaskIds;
|
||||
|
||||
@Column(name = "handled_task_ids", columnDefinition = "LONGTEXT")
|
||||
private String handledTaskIds;
|
||||
|
||||
@Column(name = "trigger_task_id")
|
||||
private Long triggerTaskId;
|
||||
|
||||
@Column(name = "activation_def_id")
|
||||
private Long activationDefId;
|
||||
|
||||
@Column(name = "activation_def_version")
|
||||
private Integer activationDefVersion;
|
||||
|
||||
@Column(name = "activation_apply_round")
|
||||
private Integer activationApplyRound;
|
||||
|
||||
/** A detached worker may act/defer only the revision it actually observed. */
|
||||
@Version
|
||||
@Column(name = "revision", nullable = false)
|
||||
private Long revision = 0L;
|
||||
|
||||
public boolean containsTask(Long id) { return contains(activationTaskIds, id); }
|
||||
public boolean handledTask(Long id) { return contains(handledTaskIds, id); }
|
||||
public void addTask(Long id) { if (!containsTask(id)) activationTaskIds = append(activationTaskIds, id); }
|
||||
public void addHandledTask(Long id) { if (!handledTask(id)) handledTaskIds = append(handledTaskIds, id); }
|
||||
private static boolean contains(String ids, Long id) { return ids != null && id != null && ids.contains("," + id + ","); }
|
||||
private static String append(String ids, Long id) {
|
||||
if (id == null || id <= 0) throw new IllegalArgumentException("Missing activation task identity");
|
||||
return (ids == null ? "," : ids) + id + ",";
|
||||
}
|
||||
|
||||
/** 出边名(可空=引擎默认路由) */
|
||||
@Column(name = "edge_name", length = 128)
|
||||
private String edgeName;
|
||||
|
||||
/** 办理人随行(推进链操作人信封,可空) */
|
||||
@Column(name = "assignee_id")
|
||||
private Integer assigneeId;
|
||||
|
||||
@Column(name = "assignee_name", length = 64)
|
||||
private String assigneeName;
|
||||
|
||||
/** PENDING=待执行;DONE=已执行(含推进判定为无需推进的幂等结论);EXHAUSTED=重试耗尽留人工 */
|
||||
@Column(name = "status", nullable = false, length = 16)
|
||||
private String status = STATE_PENDING;
|
||||
|
||||
@Column(name = "attempts", nullable = false)
|
||||
private Integer attempts = 0;
|
||||
|
||||
/** 退避到期时间(耗尽前按指数退避续扫) */
|
||||
@Column(name = "next_retry_at")
|
||||
private LocalDateTime nextRetryAt;
|
||||
|
||||
@Column(name = "last_error", length = 255)
|
||||
private String lastError;
|
||||
}
|
||||
Reference in New Issue
Block a user