按《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 项哈希/版本核对)。
103 lines
6.3 KiB
SQL
103 lines
6.3 KiB
SQL
-- D09 DRAFT ONLY. Never run this file against production as part of application startup.
|
|
-- Quiesce handling, transfer, return, restart and advance workers before an audited legacy backfill.
|
|
-- Apply additive columns first, then deploy ALL D09 writers together; mixed old/new writers are unsafe.
|
|
-- The root task is an identity, not a completion-order comparison. Never backfill MAX(task_id).
|
|
ALTER TABLE flw_advance_intent
|
|
ADD COLUMN activation_task_id BIGINT NULL,
|
|
ADD COLUMN activation_task_ids LONGTEXT NULL,
|
|
ADD COLUMN handled_task_ids LONGTEXT NULL,
|
|
ADD COLUMN trigger_task_id BIGINT NULL,
|
|
ADD COLUMN activation_def_id BIGINT NULL,
|
|
ADD COLUMN activation_def_version INT NULL,
|
|
ADD COLUMN activation_apply_round INT NULL,
|
|
ADD COLUMN revision BIGINT NOT NULL DEFAULT 0,
|
|
ADD UNIQUE KEY uk_flw_advance_activation (activation_task_id);
|
|
|
|
-- Inventory is a rollout gate, not an automatic guess of the historical cohort/last handler:
|
|
-- SELECT instance_id,node_id,id,status FROM flw_advance_intent WHERE activation_task_id IS NULL AND status IN ('PENDING','EXHAUSTED');
|
|
-- NULL work without a registered successor is held EXHAUSTED, never executed or silently marked DONE.
|
|
-- For a still-active legacy node, an operator supplies the EXACT audited current task cohort.
|
|
-- If pending tasks remain, p_trigger must be NULL: their future real handling re-arms the new head.
|
|
-- If all tasks are already handled, p_trigger requires independent evidence of the LAST handler;
|
|
-- equal handle_time/ID order is NOT evidence. Ambiguous history stays held for an explicit audited resolution.
|
|
-- p_audit_ref identifies that evidence. A successor is inserted BEFORE NULL work is retired, atomically.
|
|
-- Test harness extracts the procedure below as ONE JDBC statement; mysql clients need DELIMITER $$ ... $$.
|
|
DELIMITER $$
|
|
-- D09_BACKFILL_BEGIN
|
|
CREATE PROCEDURE d09_backfill_activation(IN p_instance BIGINT, IN p_node VARCHAR(64), IN p_tasks JSON,
|
|
IN p_trigger BIGINT, IN p_audit_ref VARCHAR(128))
|
|
BEGIN
|
|
DECLARE v_root BIGINT;
|
|
DECLARE v_def BIGINT;
|
|
DECLARE v_version INT;
|
|
DECLARE v_round INT;
|
|
DECLARE v_status INT;
|
|
DECLARE v_nodes TEXT;
|
|
DECLARE v_pending INT;
|
|
DECLARE v_count INT;
|
|
DECLARE v_head BIGINT;
|
|
DECLARE v_members LONGTEXT;
|
|
DECLARE v_handled JSON;
|
|
DECLARE v_edge VARCHAR(128);
|
|
DECLARE v_user INT;
|
|
DECLARE v_name VARCHAR(64);
|
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END;
|
|
IF p_audit_ref IS NULL OR LENGTH(TRIM(p_audit_ref))=0 OR p_tasks IS NULL
|
|
OR JSON_TYPE(p_tasks)<>'ARRAY' OR JSON_LENGTH(p_tasks)=0 THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 audited cohort input is required';
|
|
END IF;
|
|
IF EXISTS (SELECT 1 FROM JSON_TABLE(p_tasks,'$[*]' COLUMNS(ord FOR ORDINALITY,task_id BIGINT PATH '$')) j
|
|
WHERE JSON_TYPE(JSON_EXTRACT(p_tasks,CONCAT('$[',j.ord-1,']')))<>'INTEGER' OR j.task_id<=0) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 task identities must be positive integers';
|
|
END IF;
|
|
START TRANSACTION;
|
|
SELECT def_id,def_version,apply_round,status,current_nodes INTO v_def,v_version,v_round,v_status,v_nodes
|
|
FROM flw_instance WHERE id=p_instance FOR UPDATE;
|
|
IF v_status IS NULL OR v_status<>10 OR FIND_IN_SET(p_node,COALESCE(v_nodes,''))=0 THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 legacy node is not currently active';
|
|
END IF;
|
|
IF EXISTS (SELECT 1 FROM flw_advance_intent WHERE instance_id=p_instance AND node_id=p_node AND activation_task_id IS NOT NULL) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 registered successor exists; do not overwrite it';
|
|
END IF;
|
|
SELECT COUNT(DISTINCT t.id),MIN(t.id) INTO v_count,v_root
|
|
FROM flw_task t JOIN JSON_TABLE(p_tasks,'$[*]' COLUMNS(task_id BIGINT PATH '$')) j ON j.task_id=t.id
|
|
WHERE t.instance_id=p_instance AND t.node_id=p_node AND t.status IN (0,1,3,5);
|
|
IF v_count<>JSON_LENGTH(p_tasks) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 cohort has duplicates, foreign or invalid tasks';
|
|
END IF;
|
|
SET v_members=CONCAT(',',REPLACE(REPLACE(REPLACE(CAST(p_tasks AS CHAR),'[',''),']',''),' ',''),',');
|
|
IF EXISTS (SELECT 1 FROM flw_task WHERE instance_id=p_instance AND node_id=p_node AND status=0
|
|
AND LOCATE(CONCAT(',',id,','),v_members)=0) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 cohort omits current pending tasks';
|
|
END IF;
|
|
SELECT COUNT(*) INTO v_pending FROM flw_task WHERE instance_id=p_instance AND node_id=p_node AND status=0;
|
|
IF (v_pending=0 AND p_trigger IS NULL) OR (v_pending>0 AND p_trigger IS NOT NULL) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 pending cohort waits; completed cohort needs proven last handler';
|
|
END IF;
|
|
IF p_trigger IS NOT NULL THEN
|
|
IF LOCATE(CONCAT(',',p_trigger,','),v_members)=0
|
|
OR NOT EXISTS (SELECT 1 FROM flw_task WHERE id=p_trigger AND status=1) THEN
|
|
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='D09 last handler is not an approved cohort member';
|
|
END IF;
|
|
SELECT edge_name,assignee_id,assignee_name INTO v_edge,v_user,v_name FROM flw_task WHERE id=p_trigger;
|
|
END IF;
|
|
SELECT JSON_ARRAYAGG(id) INTO v_handled FROM flw_task
|
|
WHERE instance_id=p_instance AND node_id=p_node AND status<>0 AND LOCATE(CONCAT(',',id,','),v_members)>0;
|
|
INSERT INTO flw_advance_intent(instance_id,node_id,activation_task_id,activation_task_ids,handled_task_ids,
|
|
trigger_task_id,activation_def_id,activation_def_version,activation_apply_round,revision,
|
|
edge_name,assignee_id,assignee_name,status,attempts,next_retry_at,last_error,create_time,update_time,create_by)
|
|
VALUES(p_instance,p_node,v_root,v_members,
|
|
IF(v_handled IS NULL,NULL,CONCAT(',',REPLACE(REPLACE(REPLACE(CAST(v_handled AS CHAR),'[',''),']',''),' ',''),',')),
|
|
p_trigger,v_def,v_version,v_round,0,v_edge,v_user,v_name,IF(p_trigger IS NULL,'DONE','PENDING'),0,NOW(),
|
|
LEFT(CONCAT('D09_AUDITED_BACKFILL: ',p_audit_ref),255),NOW(),NOW(),LEFT(p_audit_ref,64));
|
|
SET v_head=LAST_INSERT_ID();
|
|
UPDATE flw_advance_intent SET status='DONE',revision=revision+1,update_time=NOW(),
|
|
last_error=LEFT(CONCAT('D09_HANDOFF: successor=',v_head,' audit=',p_audit_ref),255)
|
|
WHERE instance_id=p_instance AND node_id=p_node AND activation_task_id IS NULL AND status IN ('PENDING','EXHAUSTED');
|
|
COMMIT;
|
|
END
|
|
-- D09_BACKFILL_END
|
|
$$
|
|
DELIMITER ;
|
|
-- No CALL is executed by this draft. Audit the cohort before an explicitly approved maintenance invocation.
|