Skip to content
bitzorcas
中EN

Guide

Workflow Migrator

按 bitzorcas 或 saury 来源把旧流程定义转成新引擎 JSON DSL,写出 sidecar 报告,并在隔离目标上 Deploy 与 Publish。

Last updated

BitzOrcas.Workflow.Migrator 是平台级 Tooling,只迁移流程定义。它按 source 读取 BitzOrcas 五表或 Saury T_WorkflowDefinition* 一组表,转换成新引擎 JSON DSL。非 dry run 时通过真实 Workflow IRepositoryService 执行 DeployAsync 与 PublishDeploymentAsync。Saury 表结构知识只留在 Tooling,不得进入 Framework 或 Platform 运行时。

迁移阶段

是否bitzorcassaury有无是否

批准的配置

source 已指定?

使用显式 bitzorcas 或 saury

探测 FlowDefine 或 T_WorkflowDefinition

来源

读取五张 Flow* 表

读取 Saury 定义表

FlowDefinitionConverter

SauryFlowConverter

控制台 warnings 与 JSON DSL

sidecar 迁移报告

output-dir?

写出 json 与 markdown

仅控制台

DryRun?

人工语义评审

Deploy 新版本

Publish 租户或分所绑定

目标租户 smoke 与回归

读图:配置批准后先定来源,再分两路读表。BitzOrcas 走既有五表转换器,行为保持不变。Saury 走步骤树转换器并额外产出 sidecar 报告。output-dir 只影响是否落盘;DryRun 决定是否部署。警告不增加失败计数,转换成功也不等于业务语义等价。

准备

  1. 源库是只读 snapshot,记录 snapshot 时间与 schema 版本。
  2. 目标是隔离迁移库,不是生产租户数据库。
  3. 选定 source。不传时自动探测:存在 FlowDefine 用 bitzorcas,存在 T_WorkflowDefinition 用 saury;两张表都在时回退 bitzorcas;都没有则抛错退出 99。
  4. flow-names 写成精确列表。BitzOrcas 过滤 FlowDefine.Name;Saury 过滤 T_WorkflowDefinition.Name。空值会迁移全部启用定义。
  5. Saury 若要按分所收窄权限和租户绑定,准备整数 office-id。
  6. 冻结旧定义编辑窗口;本工具不锁源表。
  7. 明确实例切换策略;本工具不搬迁 T_Workflow 或 BitzOrcas 在途实例。
Terminal window
# 构建工具与 Workflow 相关项目,先暴露 metadata/adapter 漂移。
dotnet build src/Tooling/BitzOrcas.Workflow.Migrator \
--configuration Release
# 转换器与 DSL 编译单测。
dotnet test tests/BitzOrcas.Workflow.Migrator.Tests \
--configuration Release

缺少任一连接串时打印 usage 并返回 1。没有独立 help 开关。

配置接线

程序加载 appsettings.json、appsettings.local.json、MIGRATOR_ 环境变量和命令行,绑定 Migrator section,再由 MigratorCli.ApplyOverrides 叠加 kebab-case 开关。优先级是:命令行开关大于已绑定的 JSON 与环境变量。

{
"Migrator": {
"SourceConnectionString": "Server=legacy-staging;Database=WorkflowSnapshot;User Id=wf_migrator;Password=Secr3t!P@ss;TrustServerCertificate=True",
"TargetConnectionString": "Server=target-isolated;Database=WorkflowMigration;User Id=wf_migrator;Password=Secr3t!P@ss;TrustServerCertificate=True",
"TenantId": "PLATFORM",
"DryRun": true,
"FlowNames": "MatterApproval,SealApply",
"Source": "saury",
"OfficeId": "1",
"OutputDir": "/tmp/wf-migrator-out"
}
}

把含密码的文件保存为项目目录下的 appsettings.local.json,确认被 Git 忽略。连接串中的 Password/Pwd 在摘要日志会掩码,但异常、shell、驱动日志仍按敏感制品处理。

开关配置键含义
source-connection / target-connectionSourceConnectionString / TargetConnectionString源库与目标库
sourceSourcebitzorcas 或 saury;空则探测
office-idOfficeId仅 saury:过滤权限与 T_TenantWorkflowDefinition
output-dirOutputDir写出 {key}.v{version}.json 与 sidecar 报告
flow-namesFlowNames逗号分隔流程名
tenant-idTenantId目标租户,默认 PLATFORM
dry-runDryRun只转换不部署

实施

在工具项目目录运行,确保 local 配置被加载。

Terminal window
cd src/Tooling/BitzOrcas.Workflow.Migrator
# 既有 BitzOrcas 调用:不传 source,行为仍走五表路径。
dotnet run --configuration Release -- \
--dry-run \
--output-dir /tmp/wf-bitzorcas
# Saury 产品库:显式来源,可按流程名与分所收窄。
dotnet run --configuration Release -- \
--source saury \
--dry-run \
--office-id 1 \
--flow-names MatterApproval \
--output-dir /tmp/wf-saury

output-dir 对两种来源都写 {key}.v{version}.json、{key}.v{version}.migration-report.md,并再写一份 {key}.migration-report.md。不传则只打印控制台。

BitzOrcas 五表路径

FlowDefine 读取 IsDeleted = 0 OR IsDeleted IS NULL。随后按定义 ID 读取按 NodeStep 排序的节点、LaneType = 0 的连线、经 FlowControl join 的条件,以及全部审批人。FlowDefinitionConverter 的节点、会签、退回、条件映射保持原行为,不因 Saury 来源改写。

Legacy NodeTypeJSON DSL type说明
StartstartEvent起点
ApproveruserTask审批任务
FinishendEvent终点
其他值userTask仅 warning,并默认降级

条件支持 GreaterThan、GreaterThanOrEqual、LessThan、LessThanOrEqual、Equal、NotEqual。Contains 返回空,边不带 condition。

Saury 定义表路径

SauryFlowReader 读取 T_WorkflowDefinition、T_WorkflowDefinitionStep、T_WorkflowDefinitionState、T_WorkflowPermission、T_WorkflowOrganizationUnits、T_TenantWorkflowDefinition。T_Workflow 实例表不读。只取 IsActive = 1 的定义,按 Name、Version 排序。

版本解析对齐 DefinitionManager.GetDefinitionState:优先 T_TenantWorkflowDefinition 指定的 DefinitionId,否则回退 Version = 1,再按 Version 降序。发布时:无绑定则把最高 Version 发布到 officeId 为空的租户绑定;有绑定则按 OfficeId 发布对应版本。

Saury新 DSL规则
Name / Version / 显示名key / version / namekey = SanitizeKey(Name),与 BitzOrcas 清理规则一致
顶层步骤链nodes + edges链首补 start,链尾补 end
WaitForuserTask权限按 WaitForId 映射;提供 office-id 时按 OfficeId 过滤;无权限记录不设 participants 并记 warning
T_WorkflowOrganizationUnitsdataScopeOfficeLevel 1/2/3 对应 Tenant/Office/Department;非空组织机构列表对应 Custom
IfexclusiveGateway连续 If 收成一个网关;Condition 做机械转译
类名为 Return / Redo 的动作rollbackReturn 倾向 mode: start,Redo 用 prev
类名为 Approve / Confirm / End 等折叠为边业务副作用不进 DSL,StateId 进报告
链首 Apply折叠申请人提交属于发起方逻辑
While / ForEach / Schedule / Recur不迁移记 warning
T_WorkflowDefinitionStatesidecar 状态映射表不进 DSL

WorkflowCore.Primitives. 前缀判定控制原语,兼容有无程序集后缀。Condition 只转译 Data.X / data.X、比较与逻辑运算符、数字/引号字符串/true/false/null。方法调用如 .Contains(value) 不转译:该边不带 condition,原文进 warning 与 sidecar。

sidecar 迁移报告

Saury 每条定义产出一份 Markdown,供业务模块实现 IBusinessIntegrationCallback.OnStatusChangedAsync 时对照 BusinessStatusChange.ToFlowState 与 ToNodePrefix:

  1. 状态映射表:老 StateId / Name / DisplayName / IsAudit / Category 对照新 NodePrefix 与建议 FlowState。
  2. Hook 清单:每个业务步骤的 Name、DisplayName、StepType 全名、IsAudit、所在环节、建议写回状态。StepType 直接来自库,不解析 Saury 源码。
  3. 转译失败清单:未转译 Condition、未迁移控制原语、无 participants 的 userTask、降级的 dataScope。

BitzOrcas 路径在指定 output-dir 时也会写报告,但状态映射与 Hook 清单为空,失败清单只收 converter warnings。

部署与发布

非 dry run 通过 SqlSugar Workflow store 构建引擎。DeployAsync(key, name, jsonDsl, "migrator", tenantId) 创建不可变版本;再用返回的 DefinitionId 调用 PublishDeploymentAsync。BitzOrcas 的 office 参数仍传 null。Saury 对每个 Office 绑定传入该分所字符串。

这两步不是本工具显式包裹的原子事务。Deploy 成功而 Publish 失败时,目标可能留下未发布版本;重跑前必须查询目标版本与 binding。

Terminal window
# 确认隔离目标后关闭 DryRun。
dotnet run --configuration Release -- \
--source saury \
--output-dir /tmp/wf-saury \
> "$MIGRATION_EVIDENCE/workflow-deploy.log" 2>&1
rg -n '部署成功|部署失败|发布部署绑定失败|失败:' \
"$MIGRATION_EVIDENCE/workflow-deploy.log"

验证

  1. dry-run 每个 JSON 能被 DefinitionCompiler 反序列化并编译;见 tests/BitzOrcas.Workflow.Migrator.Tests。
  2. sidecar 三节齐全,Hook 的 StepType 与库中类型全名一致。
  3. 同一输入两次运行,JSON 与报告逐字节一致。
  4. 不带 source 的既有调用仍走 BitzOrcas 五表路径。
  5. 无权限 WaitFor 只有 warning,不伪造审批人。
  6. 方法调用条件没有被写进边。
  7. 目标租户能按 published binding 启动一条新实例。
Terminal window
# 转换器单测与 Workflow 相关架构合同。
dotnet test tests/BitzOrcas.Workflow.Migrator.Tests \
--configuration Release
dotnet test tests/BitzOrcas.Architecture.Tests \
--configuration Release \
--filter 'FullyQualifiedName~Workflow'

回滚

  1. 保留 dry-run 日志、JSON 与 sidecar 作为审批制品。
  2. 隔离目标上的未发布 Definition 可删除或停用;不要在生产直接重跑覆盖。
  3. 已 Publish 的绑定用 RollbackDeploymentAsync 回到 PreviousDefinitionId,已发起实例仍锁定旧快照。
  4. 源库保持只读 snapshot,不在本工具内回写 Saury 或 BitzOrcas 旧表。
  5. 业务回调代码属于业务模块,不随本工具回滚。

退出码

Code当前含义自动化处理
0所有流程未抛异常;可能仍有 warnings继续语义审查,不自动放行
1连接串配置缺失阻塞,修配置接线
2至少一个流程转换或部署失败阻塞,对账部分成功
3Ctrl+C / cancellation阻塞,检查部分部署
99未处理异常或来源探测失败阻塞,保存掩码日志

批量运行遇到单个流程失败会继续处理其他流程,因此 code 2 代表可能部分成功。

交付清单

  • snapshot 源和隔离目标身份可追溯;
  • 显式或探测后的 source 已记录;
  • dry-run 每个 warning 都有接受、修复或阻塞结论;
  • Saury sidecar 三节已交给业务模块做回调实现;
  • definition key、版本、Deploy 与 Publish binding 在目标核对;
  • 声明不迁移实例,并完成新旧流量切换方案;
  • 日志、JSON 与报告按敏感制品存储。

另见

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%