制作Automatonymous sagas多租户

时间:2015-07-29 16:10:22

标签: multi-tenant masstransit saga automatonymous

由于Chris Patterson的一些help,我们已成功将我们的多租户策略与MassTransit整合在一起。然而,我们在获取我们的(Automatonymous)传奇多租户方面遇到了绊脚石。我有一些有用的东西但我对此并不满意。我们正在使用“每个租户的架构”数据库策略,但是如果这是解决它的最简洁的方法,我们愿意为sagas进行灵活处理。

我们在所有邮件的标头上都有租户ID。我们将其从IConsumeContext<>传入消息中删除,并将其重新放回IPublishContext<>外发消息。这适用于ISagaRepository<>.GetSaga(...),因为其中一个参数是IConsumeContext<>。问题是,当我们调用其他ISagaRepository<>方法时,它们没有IConsumeContext<>,我们无法通过存储库中的租户进行过滤。如果我们坚持使用当前的数据库策略,我们就知道了租户,因此我们知道要触及的架构。如果我们改为拥有集中租户表,我们必须在过滤中包含租户,因为它所关联的东西在租户中并不一定是唯一的。

基于我目前的理解,PropertySagaLocator<,>似乎是关键点。在Find(IConsumeContext<>)方法中,我们需要可访问的租户上下文,但它不会传递给saga存储库。

在我目前的尝试中,我已经为多租户创建了一个属性saga定位器,它与专门的租户saga存储库一起工作,并为其提供了适当使用其.Where(...)方法所需的租户上下文。但是这里变得丑陋。 PropertySagaLocator<,>具体类正由Automatonymous实例化,因此为了交换它,我必须从一个.StateMachineSaga(...)扩展方法开始在Automatonymous的边缘,并一直交换出具体的类通过使用PropertySagaLocator<,>,它与MassTransit集成,因为它是一系列具体的类,一直相互实例化。我不喜欢通过Automatonymous进行如此深入的切割,但在我看来,无论我们采用“每个租户架构”策略还是切换它,我们都需要在同一点进行集成。

这方面的另一个方面是,当使用自动标记“.Publish(...)表示法时,我们需要在外发邮件上放置租户ID。我目前正在这样做的方式是在ServiceBus上使用装饰器模式,当前我注入装饰的,特定于租户的服务总线的时候是将总线从使用上下文复制到实例状态,即在我的saga消息接收器GetHandlers()方法的覆盖中。

有没有人有过如何将Automatonymous sagas与多租户相结合的经验?我们现在所做的只是入侵,我们想要更自然的接缝。

1 个答案:

答案 0 :(得分:0)

我发现另一种方法侵入性更小,但限制性更强。具体来说,您不能使用PropertySagaLocator,即通过继承CorrelatedBy<>接口,所有相关性必须是关联ID。确保您没有进行任何StateMachineSagaRepository<>.Correlate(...)次呼叫,因为如果这样做,它将使用属性定位器,即使您为其提供实际的相关ID。

允许我做的是避免在除GetSaga(...)之外的saga存储库中使用任何方法,其中我具有我的多租户策略所需的上下文。然后我在其他人中抛出NotImplementedByDesignException

这让我只有一件事需要担心;如何在.Publish(...)次呼叫发出的邮件标题上获取租户ID。为此,我只是继承ConsumeContext<>并同时实施IConsumeContext<>,然后用Bus覆盖new属性,以便我可以在其上设置总线。然后,我有一个服务总线的装饰模式,确保总线发布租户标头,无论你调用什么方法。然后在我的saga存储库中,我将我返回的动作包装在lambda中,该lambda将我的子类消费上下文与我的特定于租户的装饰总线一起传递给消费者,而不仅仅是直接消费上下文。这导致在saga状态下设置的总线特定于该租户,并且所有外发消息都具有租户ID。