public void Handle(ExternalServiceMsg msg) { /* As established in the WebServiceEndpoint.asmx.cs comments, it's possible to * receive duplicate messages from the web service. Ways to handle duplicates * vary depending on business requirements, but for this example we'll assume * that if we receive a message with the same ServiceTransactionIdentifier * property value within 5 minutes, we should just ignore it. */ if (Data.LastSeen == DateTime.MinValue) { // This is the first message received, so set Saga data. Data.ServiceTransactionIdentifier = msg.ServiceTransactionIdentifier; Data.Payload = msg.Payload; Data.LastSeen = msg.Timestamp; // Publish an event for consumption by other subscribing services. Bus.Publish <IExternalMessageReceivedEvent>(e => { e.ServiceTransactionIdentifier = msg.ServiceTransactionIdentifier; e.Payload = msg.Payload; e.Timestamp = msg.Timestamp; } ); } // If we request a new timeout on every message received, it results in a // sliding 5-minute window. Every time we request a timeout, it clears the // previous timeout for this Saga, so we won't get multiple notifications. RequestUtcTimeout(TimeSpan.FromMinutes(5), null); }
public void Process(string transactionID, string payload) { // Translate the incoming web request into a message ExternalServiceMsg msg = new ExternalServiceMsg(); msg.ServiceTransactionIdentifier = transactionID; msg.Payload = payload; msg.Timestamp = DateTime.UtcNow; // Send the message on the Bus Global.Bus.Send(msg); /* Because the web application is not transactional, as soon as we call * Bus.Send(), the message is sent on the Bus and cannot be recalled. * * Since this is the end of the WebMethod, the web service will return * a 200 OK status code to the client. This will inform the calling * client that we successfully received and have taken ownership of * the message. * * HOWEVER, it is still possible for a server crash or network * interference to prevent the 200 OK status code from being received * by the client. This can cause the client to resend duplicate * messages. This is why we need to ensure that our receiver * (ReceivingSaga.cs) is capable of gracefully handling duplicate messages. */ }