MassTransit Saga中两请求用相同响应类型报错的解决问询
问题描述
我正在创建一个状态机,需要发送多个请求,请求定义如下:
public Request<StageState, ICloseStage, ICloseStageRequestSuccess, IRequestFailed> CloseStageRequest { get; private set; } public Request<StageState, IPublishStage, IPublishStageRequestSuccess, IRequestFailed> PublishStageRequest { get; private set; }
两个请求都可能返回IRequestFailed响应,但运行状态机时抛出错误:
System.ArgumentException : An item with the same key has already been added. Key: IRequestFailed
推测该错误是因为两个请求都使用了IRequestFailed导致的,想知道这是不是框架的默认行为?有没有办法在多个请求中复用该响应类型?我需要统一处理所有请求的IRequestFailed,后续还会添加更多请求。
解答
这确实是多数状态机框架的默认行为——框架通常会将响应类型作为唯一键来注册请求的回调处理逻辑,当多个请求使用同一个响应类型时,就会触发重复键的异常。
要实现复用IRequestFailed并统一处理的需求,可以试试以下几种方案:
基于继承扩展失败类型:为每个请求定义专属的失败接口,让它们继承自
IRequestFailed,比如:public interface ICloseStageFailed : IRequestFailed { } public interface IPublishStageFailed : IRequestFailed { }然后修改请求定义为对应专属失败类型,这样每个请求的响应键都是唯一的。在统一处理时,只需要判断响应是否实现了
IRequestFailed接口即可。自定义键的生成逻辑:如果使用的状态机框架支持自定义注册键的生成规则,可以将请求类型与响应类型的组合作为注册键,而不是仅用响应类型。这样即使响应类型相同,只要请求类型不同,键就不会重复。
全局统一错误处理:跳过在单个请求上注册
IRequestFailed的处理逻辑,转而在状态机的全局错误拦截点捕获所有IRequestFailed类型的响应,实现统一处理。这种方式不需要修改现有的请求定义,直接在全局层面做兜底处理。
内容的提问来源于stack exchange,提问作者Roman Saushkin

