0

在 Chris Patterson的帮助下,我们成功地将我们的多租户策略与 MassTransit 集成。然而,我们在获得我们的(自动)传奇多租户时遇到了困难。我有一些有用的东西,但我对它一点也不满意。我们正在使用“每个租户的模式”数据库策略,但如果这是解决问题的最干净的方法,我们愿意为 sagas 灵活使用它。

我们在所有消息的标题上都有租户 ID。我们将其从传入消息中刮下,IConsumeContext<>然后将其放回IPublishContext<>传出消息中。这很好用,ISagaRepository<>.GetSaga(...)因为它的参数之一是IConsumeContext<>. 问题是,当我们调用其他ISagaRepository<>方法时,它们没有IConsumeContext<>,并且我们无法在存储库中按租户进行过滤。如果我们坚持当前的数据库策略,我们就知道租户,所以我们知道要命中什么模式。如果我们更改为拥有集中的租户表,我们必须在过滤中包括租户,因为与之相关的事物在租户之间不一定是唯一的。

根据我目前的理解,这PropertySagaLocator<,>似乎是关键点。在它的Find(IConsumeContext<>)方法中,我们有需要访问的租户上下文,但它没有被传递到 saga 存储库。

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

另一个方面是,当使用 Automatonymous 表示法时,我们需要将租户 ID 放在传出消息.Publish(...)中。我目前这样做的方式是使用装饰器模式ServiceBus,目前我注入装饰的、特定于租户的服务总线的时间点是总线从消费上下文复制到实例状态时,即在我的saga 消息接收器GetHandlers()方法的覆盖。

有没有人有如何将 Automatonymous sagas 与多租户集成的经验?我们现在所做的似乎是侵入性的,我们希望找到更自然的接缝。

4

1 回答 1

0

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

允许我做的是避免在 saga 存储库中使用任何方法,除了GetSaga(...),我有我需要的多租户策略的上下文。然后我在其他人中扔了一个NotImplementedByDesignException

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

于 2015-07-30T15:30:10.763 回答