Files
flow-center-service/src/main/java/com/yunhai/flowcenter/entity/FlwAdvanceIntent.java
T
chenxing 500a9a2fcb 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 项哈希/版本核对)。
2026-10-27 12:05:08 +08:00

108 lines
4.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}