正如标题中我想问的是可以在BeforeTransportMessage事件中提交事务,例如,如果特定标头出现在TransportMessage中,我可以将其包装在另一个消息中并发送到其他地方并停止Rebus进一步处理。
我没有找到使用该事件的真实例子,是否有可能分享的内容?
提前致谢:)
答案 0 :(得分:1)
如果您可以安全地反序列化所有传入的消息,那么您可以这样做:
如果您正在尝试实施检查所有传入消息的过滤器,我建议您创建一个“全能”消息处理程序,即IHandleMessages<object>
的实现。我们称之为CatchAllHandler
,虽然我相信你能想出一个更好的名字;)
然后你可以
Configure.With(yourFavoriteContainerAdapter)
.UseMsmq(...)
.SpecifyOrderOfHandlers(o => o.First<CatchAllHandler>())
.Create()
.Start();
以便在所有其他处理程序之前将所有传入消息分派到CatchAllHandler
。由于它实现了IHandleMessage<object>
,因此它能够处理所有传入的消息。您的CatchAllHandler
可以执行以下操作:
public class CatchAllHandler : IHandleMessages<object> {
readonly IMessageContext context;
readonly IBus bus;
public CatchAllHandler(IMessageContext context, IBus bus) {
this.context = context;
this.bus = bus;
}
public void Handle(object message) {
if (MessageHasSpecialHeader(context.Headers)) {
// forward the current transport message in its entirety
bus.Advanced.Routing.ForwardCurrentMessage("somewhereElse");
// abort further processing of the message (i.e. do not
// dispatch to subsequent handlers in the pipeline)
context.Abort();
}
}
bool MessageHasSpecialHeader(IDictionary<string, object> headers) {
// ... look for that special header down here
}
}
但是,如果您不知道传入的byte[]
是否适合您,则需要执行其他操作。虽然在没有Rebus其余部分的情况下使用Rebus的传输实现是相当简单的,但你必须自己实现线程模型。
以下代码是一个示例(完全从内存中编写,因此您可能需要更正一些小部分),如果您使用MSMQ,这样的工作线程可能会是什么样子:
volatile bool _keepWorking = true;
public void ThreadLoop() {
using(var transport = new MsmqMessageQueue("inputQueueName")) {
while(_keepWorking) {
using(var scope = new TransactionScope())
using(var context = new AmbientTransactionContext())
{
var message = transport.ReceiveMessage(context);
if (message == null) {
Thread.Sleep(1000); //< don't punish queues too much
continue;
}
var destination = GetDestinationBasedOnWhatever(message);
transport.Send(destination, message.ToForwardableMessage());
scope.Complete();
}
}
}
}
您需要一个单独的队列来处理这种特殊类型的content-based router。你觉得那会对你有用吗?