Files
pigx/db/migration/20261014_flow_merge_tables.sql
T
PIGCLOUD 085235710b feat(flow): 持久化流程草稿提醒与可靠回调
(cherry picked from commit f6871bee7c5cddaaa5650a284ac3cc3fec16dd18)
2026-11-03 14:55:15 +08:00

101 lines
5.5 KiB
SQL

-- 仅用于已经安装旧五表版本的库。先备份、停止流程写入及后台扫描,并执行三表建表脚本。
-- 可重复执行;旧表暂保留作为核对来源,新代码不再访问。核验并备份后再清理旧表。
DELIMITER $$
DROP PROCEDURE IF EXISTS migrate_flow_three_tables$$
CREATE PROCEDURE migrate_flow_three_tables()
BEGIN
DECLARE finished INT DEFAULT 0;
DECLARE v_task VARCHAR(64);
DECLARE v_tenant BIGINT;
DECLARE v_instance VARCHAR(64);
DECLARE v_due TIMESTAMP(3);
DECLARE v_reminded TIMESTAMP(3);
DECLARE v_id VARCHAR(36);
DECLARE v_callback VARCHAR(36);
DECLARE v_attempt INT;
DECLARE v_result VARCHAR(16);
DECLARE v_detail VARCHAR(500);
DECLARE v_created TIMESTAMP(3);
DECLARE v_history LONGTEXT;
DECLARE watches CURSOR FOR SELECT task_id,tenant_id,instance_id,due_at,reminded_at FROM flow_task_watch;
DECLARE audits CURSOR FOR SELECT id,callback_id,tenant_id,attempt_no,result,detail,created_at FROM flow_callback_attempt ORDER BY created_at,id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished=1;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='flow_notice' AND column_name='status') THEN
ALTER TABLE flow_notice ADD COLUMN status VARCHAR(16) NOT NULL DEFAULT 'SENT';
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='flow_notice' AND column_name='scheduled_at') THEN
ALTER TABLE flow_notice ADD COLUMN scheduled_at TIMESTAMP(3) NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='flow_notice' AND column_name='sent_at') THEN
ALTER TABLE flow_notice ADD COLUMN sent_at TIMESTAMP(3) NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='flow_notice' AND column_name='reminder_key') THEN
ALTER TABLE flow_notice ADD COLUMN reminder_key VARCHAR(64) NULL;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='flow_notice' AND index_name='uk_notice_reminder') THEN
ALTER TABLE flow_notice ADD UNIQUE KEY uk_notice_reminder(tenant_id,reminder_key);
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='flow_notice' AND index_name='idx_notice_due') THEN
ALTER TABLE flow_notice ADD KEY idx_notice_due(status,scheduled_at);
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='flow_callback' AND column_name='history') THEN
ALTER TABLE flow_callback ADD COLUMN history LONGTEXT NULL;
END IF;
-- DDL 自动提交;以下数据搬迁独立事务,任何异常回滚数据部分,修正后可重跑。
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
UPDATE flow_notice SET sent_at=created_at WHERE status='SENT' AND sent_at IS NULL;
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='flow_task_watch') THEN
SET finished=0;
OPEN watches;
watch_loop: LOOP
FETCH watches INTO v_task,v_tenant,v_instance,v_due,v_reminded;
IF finished=1 THEN LEAVE watch_loop; END IF;
IF NOT EXISTS (SELECT 1 FROM flow_notice WHERE tenant_id=v_tenant AND reminder_key=v_task) THEN
IF (SELECT COUNT(*) FROM flow_notice WHERE tenant_id=v_tenant AND event_key=CONCAT('OVERDUE:',v_task) AND kind='OVERDUE') > 1 THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Multiple overdue notices for one watch; inspect before migration';
END IF;
IF EXISTS (SELECT 1 FROM flow_notice WHERE tenant_id=v_tenant AND event_key=CONCAT('OVERDUE:',v_task) AND kind='OVERDUE') THEN
UPDATE flow_notice SET reminder_key=v_task,scheduled_at=v_due,sent_at=COALESCE(v_reminded,sent_at)
WHERE tenant_id=v_tenant AND event_key=CONCAT('OVERDUE:',v_task) AND kind='OVERDUE';
ELSE
INSERT INTO flow_notice(id,tenant_id,user_id,event_key,kind,title,task_id,instance_id,created_at,status,scheduled_at,sent_at,reminder_key)
VALUES(UUID(),v_tenant,'',CONCAT('OVERDUE:',v_task),'OVERDUE','流程任务',v_task,v_instance,CURRENT_TIMESTAMP(3),
CASE WHEN v_reminded IS NOT NULL THEN 'SENT' WHEN v_due IS NULL THEN 'DISABLED' ELSE 'PENDING' END,v_due,v_reminded,v_task);
END IF;
END IF;
END LOOP;
CLOSE watches;
END IF;
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='flow_callback_attempt') THEN
SET finished=0;
OPEN audits;
audit_loop: LOOP
FETCH audits INTO v_id,v_callback,v_tenant,v_attempt,v_result,v_detail,v_created;
IF finished=1 THEN LEAVE audit_loop; END IF;
IF NOT EXISTS (SELECT 1 FROM flow_callback WHERE id=v_callback AND tenant_id=v_tenant) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='Orphan callback attempt; retain old tables and inspect';
END IF;
SELECT COALESCE(history,'[]') INTO v_history FROM flow_callback WHERE id=v_callback AND tenant_id=v_tenant FOR UPDATE;
IF JSON_SEARCH(v_history,'one',v_id,NULL,'$[*].id') IS NULL THEN
UPDATE flow_callback SET history=JSON_ARRAY_APPEND(v_history,'$',JSON_OBJECT('id',v_id,'attempt_no',v_attempt,
'result',v_result,'detail',v_detail,'created_at',DATE_FORMAT(v_created,'%Y-%m-%d %H:%i:%s.%f')))
WHERE id=v_callback AND tenant_id=v_tenant;
END IF;
END LOOP;
CLOSE audits;
END IF;
COMMIT;
END;
END$$
CALL migrate_flow_three_tables()$$
DROP PROCEDURE migrate_flow_three_tables$$
DELIMITER ;