ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Elsa 3 活动输出转换器(Output Converters)数据模型深度解析:从绑定、注册到故障处理

Elsa 3 活动输出转换器(Output Converters)数据模型深度解析:从绑定、注册到故障处理 后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载本文基于specs/012-output-converters/data-model.md展开。Elsa 3 的活动输出转换器Output Converters是一套可扩展机制工作流作者可以在活动输出 → 变量/工作流输出这条绑定链路上显式挂载一个已注册的转换器让目标变量拿到的是转换后的 Bound Value而活动自身的原生输出Native Output原封不动地保留在活动输出寄存器与诊断日志中。读完本文你将掌握该特性的完整数据模型——输出绑定、转换器配置、注册与描述符、转换上下文、目标解析、结构化错误与状态机——并能结合仓库源码理解其端到端实现。特性定位为什么需要绑定级输出转换Elsa 3 中活动的每个输出Activity Output通过Output/OutputT绑定Output Binding关联到一个目标Destination这个目标通常是一个变量variable或工作流输出workflow output。传统绑定把活动原生值直接写入目标而输出转换器允许在写入前插入一次显式、同步、确定性的变换。这套模型的核心原则体现在四个不变式上原生值不变活动输出寄存器、工作流日志、API 响应与诊断永远暴露原生 Activity Output参见 spec.md 的 FR-005、FR-006转换只作用于绑定边界只有交付给目标的 Bound Value 才经历转换FR-007 明确转换必须在 Output Binding 边界同步完成显式选择、绝不自动推断系统不会根据源/目标类型猜测该用哪个转换器FR-015必须由作者显式配置 Converter ID可选、向后兼容未配置转换器的绑定序列化形状与赋值行为与旧版本完全一致FR-003。一、输出绑定Output Binding一条可选的新关系在既有Output/OutputT绑定模型之上本特性只新增一个可选关系成员说明Converter零或一个转换器配置Converter Configuration内存引用Memory Reference保持不变它仍然是目标身份destination identity的唯一标识原生输出类型保持不变强类型输出为T无类型输出为object两条验证规则构成了绑定的合法性前提转换器配置必须指向可解析的目标若绑定了Converter则该输出必须关联到一个可解析的变量或工作流输出无配置则行为不变没有Converter的绑定序列化结果与既有赋值路径完全一致不触发任何转换器查找、校验或调用。仓库中Output模型的Converter属性正是这一关系的落地见 src/modules/Elsa.Workflows.Core/Models/Output.cs。在运行时边界ActivityExecutionContext.Set中代码先检查output?.Converter null为空则走原有赋值路径写入表达式内存块 记录活动输出非空才进入转换流程见 ActivityExecutionContext.cs。二、转换器配置Converter Configuration持久化的唯一入口每个绑定可携带一份持久化的转换器配置字段只有两个Id必填、非空的稳定转换器 IDSettings可选 JSON 对象在持久化或调用前会被克隆保证不可变语义。序列化形态如下绑定 JSON 中新增一个可选converter对象{ typeName: String, memoryReference: { id: resultVariable }, converter: { id: sample.to-text, settings: { format: compact } } }注意两个约束配置中只允许出现 Converter ID 与设置绝不允许持久化实现类型名、实例、描述符或显示元数据FR-004。代码层面OutputConverterConfiguration是sealed record构造时即对Settings执行settings?.Clone()Id空值时被规整为空字符串见 OutputConverterConfiguration.cs。三、转换器注册Output Converter RegistrationKeyed DI 与唯一性注册信息由三个要素组成成员说明Descriptor不可变的转换器描述符Converter DescriptorServiceKey精确的 Converter ID作为 Keyed DI 的解析键ServiceLifetime注册生命周期Transient/Scoped/Singleton三者之一唯一性规则非常严格精确的、区分大小写的 ID 是唯一的查找使用 ordinal 大小写敏感比较仅大小写不同的 ID 同样禁止——注册期即抛错而不是依赖注册顺序。仓库中OutputConverterServiceCollectionExtensions.AddOutputConverterTConverter实现了注册入口它先校验描述符、用StringComparison.OrdinalIgnoreCase检查历史注册再把不可变OutputConverterRegistration注册为单例同时通过ServiceDescriptor.DescribeKeyed以 Converter ID 为 key 注册实现见 OutputConverterServiceCollectionExtensions.cs。注册集合构造时OutputConverterRegistry会再次以StringComparer.OrdinalIgnoreCase分组检查重复并拒绝 open-generic 的源/结果类型见 OutputConverterRegistry.cs。注册代码示例摘自 doc/wiki/output-converters.mdservices.AddOutputConverterNumberToTextConverter( new OutputConverterDescriptor( sample.number-to-text.v1, typeof(decimal), typeof(string), Number to text, Formats a decimal using an explicit invariant format., schemaDocument.RootElement));默认生命周期为Scoped实现类从当前工作流执行作用域workflow execution scope中按 ID 解析注册表只缓存描述符与注册信息绝不缓存 scoped 转换器实例FR-024。四、转换器描述符Converter Descriptor面向发现的中立元数据描述符是服务器拥有server-owned的发现元数据字段如下字段说明Id稳定的语义标识持久化公共契约SourceType支持的源 CLR 类型ResultType声明的结果 CLR 类型DisplayName可发现的展示文本Description可选的可发现描述SettingsSchema可选的克隆 JSON Schema关键点API 投影时CLR 类型会被替换为注册的类型别名或安全类型名并省略所有服务注册数据生命周期、实现类型、keyed 服务细节一律不外泄。参考 API 客户端模型 src/clients/Elsa.Api.Client/Resources/OutputConverters/Models/OutputConverterDescriptor.cs。兼容性判定在FindCompatible中实现描述符兼容当且仅当SourceType.IsAssignableFrom(声明的输出类型)且ResultType可赋值给目标类型对NullableT目标做了底层类型展开见 OutputConverterRegistry.cs。五、转换上下文Output Conversion Context极简且不可变每次转换调用转换器只拿到一个不可变的上下文成员说明Value非空的原生活动输出SourceType声明的活动输出类型DestinationType解析出的声明目标类型Settings不可变 / 克隆后的 JSON 设置上下文里既没有工作流执行对象也没有服务提供者FR-021/FR-022——这从机制上杜绝了转换器偷偷修改工作流状态或执行服务定位式取依赖。依赖只能通过构造函数注入获得。仓库实现OutputConversionContext同样在构造时克隆Settings见 OutputConversionContext.cs。转换器接口契约见 IOutputConverter.cspublic interface IOutputConverter { object? Convert(OutputConversionContext context); IEnumerablestring ValidateSettings(JsonElement? settings) []; }实现参考NumberToTextConverter的典型写法从context.Settings读取format用CultureInfo.InvariantCulture显式格式化不做任何 I/O 与状态变更完整示例见 doc/wiki/output-converters.md。六、目标Destination变量或工作流输出的统一视图目标对象的四个字段字段说明Id内存引用或工作流输出身份Type解析后的 CLR 类型AllowsNull引用类型与NullableT为true其他值类型为falseKindVariable或WorkflowOutput目标的解析分两个层面定义期解析从最近的变量容器作用域逐级向外查找找不到再查工作流输出运行时解析使用已声明的内存块元数据memory-block metadata。由于 Elsa 目前没有变量/工作流输出的可空引用元数据AllowsNull完全由 CLR 可表示性决定引用类型或NullableT允许 null这是 research.md 中记录的设计决策避免把本特性扩成全局可空性模型。七、输出转换错误Output Conversion Error结构化、隐私安全的故障转换失败不会静默吞掉而是抛出专门的OutputConversionExceptionExceptions/OutputConversionException.cs字段如下字段说明ConverterId配置的转换器 IDStage失败阶段见下ActivityId/ActivityType产生输出的活动身份与类型OutputName声明的输出名DestinationId可选的目标 IDSourceTypeName/DestinationTypeName声明类型的安全名称InnerException可选的原始转换器异常失败阶段枚举Enums/OutputConversionFailureStage.csResolution | SettingsValidation | SourceCompatibility | Invocation | ResultValidation安全策略有两条硬约束只有安全字段会被复制到持久化的异常元数据GetSafeMetadata只导出 ID、阶段、活动信息、输出名、类型名原生值与原始设置永不进入异常消息——默认消息仅包含 Converter ID、阶段、输出名与活动 ID防止敏感数据泄漏FR-032。在OutputConverterInvoker中可以看到完整的五阶段编排解析注册 → 校验源兼容性与结果可赋值性 → 从活动作用域解析 keyed 服务 → 校验设置JSON Schema 转换器自有校验→ 调用Convert→ 校验结果与可空性任一步失败都生成带阶段信息的OutputConversionException见 OutputConverterInvoker.cs。八、状态转换一条清晰的赋值决策路径data-model.md 给出的状态机完整描述了从绑定到写入的全过程Unconfigured Binding └─ assign native value using existing path Configured Binding ├─ record native output ├─ native null → validate destination nullability → write null └─ non-null ├─ resolve registration and destination ├─ validate source, destination, and settings ├─ invoke converter ├─ validate result and nullability ├─ success → write Bound Value └─ failure → fault activity; destination unchanged几个必须强调的语义先记录、后转换原生值先写入活动输出寄存器即便随后转换失败诊断里仍能看到原生值research.md 明确这是选择ActivityExecutionContext.Set作为编排点的理由null 绕过原生值为 null 时直接跳过Convert调用FR-008仅在目标允许 null 时才写入 null原子写入转换与结果校验全部完成之后才写目标因此失败时目标保持原值不变FR-010/FR-011失败即故障失败通过 Elsa 常规的活动故障管道上报不引入转换器专属重试机制同时保留原始异常作为内层异常FR-029/FR-031。这一流程在 ActivityExecutionContext.cs 中有完整代码印证先RecordActivityOutput记录原生值再解析 destination处理 null 分支随后调用 invoker 完成转换链。九、定义期校验与运行时复核双重防线为确保持久化工作流活得比部署长系统在两个时点执行同样的安全校验FR-026/FR-027定义接受/物化时ValidateOutputConverters作为WorkflowDefinitionValidating通知处理器遍历物化后的工作流图对每个带Converter的绑定依次校验ID 非空 → 目标可解析 → 转换器已注册 → 源类型兼容 → 结果类型可赋值 → 设置校验通过任何问题都以可操作的验证错误返回见 ValidateOutputConverters.cs运行时赋值时OutputConverterInvoker重复全部安全检查专门捕获校验时注册过、运行时已删除/被不兼容替换这类部署注册漂移。十、API 发现与 Studio服务器拥有的描述符查询转换器的发现完全由服务器端持有Studio 不维护硬编码目录FR-036。查询端点GET /descriptors/output-converters?sourceTypeDecimaldestinationTypeString两个查询参数均为必填的注册类型别名或可解析的安全类型名缺失或不可解析返回400授权要求read:*或read:output-converters见 Endpoint.cs响应仅包含id、sourceTypeName、resultTypeName、displayName、description、可选的settingsSchema——绝不包含实现类型、实例、服务键、生命周期或工作流里的设置值API 客户端契约IOutputConvertersApi.ListAsync以SourceType/DestinationType查询并镜像安全描述符形状见 src/clients/Elsa.Api.Client/Resources/OutputConverters/Contracts/IOutputConvertersApi.cs。Studio 端遵循完整作者工作流选择目标 → 按声明类型过滤兼容转换器 → 有 Schema 时用 schema 驱动的字段编辑器、无 Schema 时用原始 JSON 编辑器 → 保存/重开不丢配置 → 清除转换器后恢复未转换赋值行为。版本偏斜也有明确约定旧服务器不提供发现能力时Studio 隐藏/禁用新控件但不删除已持久化的转换器配置未知的持久化 Converter ID 保持可见并标注校验状态详见 contracts/studio-contract.md 与 contracts/rest-api.md。十一、测试覆盖与边界情况仓库的单元测试与组件测试为该特性提供了完整验证网可作为阅读源码的路线图注册与唯一性test/unit/Elsa.Workflows.Core.UnitTests/OutputConverters/OutputConverterRegistrationTests.cs、OutputConverterRegistryTests.cs调用链与阶段错误OutputConverterInvokerTests.cs、OutputConversionExceptionStateTests.cs运行时边界ActivityExecutionContextOutputConversionTests.cs目标解析OutputBindingDestinationResolverTests.cs定义期校验test/unit/Elsa.Workflows.Management.UnitTests/Handlers/Notifications/ValidateOutputConvertersTests.csAPI 端点test/unit/Elsa.Workflows.Api.UnitTests/OutputConverters/OutputConverterEndpointTests.cs端到端场景与 API 客户端test/component/Elsa.Workflows.ComponentTests/Scenarios/OutputConverters/OutputConverterTests.cs。data-model.md 与 spec.md 明确要求测试覆盖序列化、类型兼容、可空性、生命周期、隐私、重放/重试行为、API 发现、Studio 往返、版本偏斜以及未配置转换器的原路径不变FR-042。边界情况还包括配置了转换器但没有变量/工作流输出目标、目标类型为object/可空值类型/不可空值类型/未知类型、非空输入转换为 null、源类型是基类/接口、结果声明不可赋值给目标、两次注册仅大小写不同、设置缺失/为空/畸形/违反 Schema、旧客户端编辑含转换器配置的工作流、以及尝试配置多个转换器或 open-generic 转换器。十二、操作建议与设计约束从 doc/wiki/output-converters.md 提炼的实战纪律ID 是持久化公共契约查找必须大小写敏感行为、设置或结果语义发生破坏性变更时换一个新版本化 ID绝不复用旧 ID确定性优先locale、时区、舍入等环境性选择必须显式化为设置项转换器内不得执行 I/O、不得变更工作流状态把移除当部署漂移已发布工作流引用的转换器被移除后赋值时活动会按正常故障管道报错目标保持原值、原生输出仍可诊断异步或有副作用请换姿势需要异步或副作用的变换应使用活动输入或显式活动完成而不是输出转换器。设计决策的完整论证记录在 ADR 0011绑定期同步转换、ADR 0012显式稳定标识 与 ADR 0013服务器拥有发现 中。小结从数据模型视角看Elsa 3 的输出转换器是一套克制而完整的设计绑定只新增一个可选关系、配置只持久化 ID 与设置、上下文只携带四个不可变字段、错误只导出结构化安全元数据。它把显式、同步、确定性、可发现、隐私安全五条原则落到了每个数据实体上同时通过无配置路径零开销、行为不变保证了向后兼容。无论你是要注册自定义转换器的扩展开发者还是想在设计器中配置转换的工作流作者都可以以本文的数据模型为索引直接进入 specs/012-output-converters 目录下的 spec、contracts 与测试继续深入。赞分享后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载相关推荐Elsa 3 输出转换器Output Converters完全指南在绑定边界同步、显式、可发现地转换 Activity 输出Elsa 3 输出转换器Output Converters完全指南在绑定边界同步、显式、可发现地转换 Activity 输出 本篇技术指南聚焦 Elsa后端工作流自动化流程编排低代码Elsa Workflows 输出转换同步绑定机制Activity Output 与 Bound Value 的边界设计深度解析Elsa Workflows 输出转换同步绑定机制Activity Output 与 Bound Value 的边界设计深度解析 导读 本文基于 Elsa W后端工作流自动化流程编排低代码ThingsBoard 数据转换器 v2simple-json 解码器输出Decoder Output格式深度解析ThingsBoard 数据转换器 v2simple json 解码器输出Decoder Output格式深度解析 在 ThingsBoard 的集成I物联网后端数据可视化消息队列上一篇Findomain项目安装与使用完全指南下一篇Threads.js 多线程编程入门指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表