// Hides the base SetResult method which we need to override // This method is called when the message is actually delivered to a ReceiveAsync call // The update to the CloseMessageSequenceNumber property of Inbound is transactional internal async Task SetResult(InboundBaseStreamWireMessage message) { var closeSeqNumber = this.stream.CloseMessageSequenceNumber; if (message.Kind == StreamWireProtocolMessageKind.CloseStream) { // The close message can be a repeat in recovery cases, but the close sequence number must be unique // It is also possible that the transaction surrounding this ReceiveAsync will abort and the message // will not in fact be consumed -- and will be received again, but the close sequence number must be unique Diagnostics.Assert( closeSeqNumber == StreamConstants.InitialValueOfLastSequenceNumberInStream || closeSeqNumber == message.MessageSequenceNumber, "{0} TraceId::{1} encountered multiple close sequence number values {2} and {3}", this.stream.Tracer, this.traceId, closeSeqNumber, message.MessageSequenceNumber); try { // this method is idempotent; the close sequence number for a stream is invariant await this.stream.SetCloseMessageSequenceNumber(message.MessageSequenceNumber, this.transactionContext); await this.stream.CloseInboundStream(this.transactionContext); } catch (Exception e) { if (e is FabricObjectClosedException) { FabricEvents.Events.DataMessageDelivery( string.Format(CultureInfo.InvariantCulture, "ObjectClosed@{0}{1}", this.traceId, this.stream.TraceType), this.stream.StreamIdentity.ToString(), message.MessageSequenceNumber, this.transactionContext.Id.ToString()); this.TrySetException(e); return; } if (e is FabricNotPrimaryException) { FabricEvents.Events.DataMessageDelivery( string.Format(CultureInfo.InvariantCulture, "NotPrimary@{0}{1}", this.traceId, this.stream.TraceType), this.stream.StreamIdentity.ToString(), message.MessageSequenceNumber, this.transactionContext.Id.ToString()); this.TrySetException(e); return; } if (e is FabricNotReadableException) { FabricEvents.Events.DataMessageDelivery( string.Format(CultureInfo.InvariantCulture, "NotReadable@{0}{1}", this.traceId, this.stream.TraceType), this.stream.StreamIdentity.ToString(), message.MessageSequenceNumber, this.transactionContext.Id.ToString()); this.TrySetException(e); return; } Tracing.WriteExceptionAsError( "DataMessageDelivery.Failure", e, "Partition::Replica {0} TraceId: {1} MessageNumber: {2} TransactionId: {3}", this.stream.TraceType, this.traceId, message.MessageSequenceNumber, this.transactionContext.Id); Diagnostics.Assert( false, "Unexpected Exception In {0} TraceId: {1} MessageNumber: {2} TransactionId: {3}", this.stream.TraceType, this.traceId, message.MessageSequenceNumber, this.transactionContext.Id); } } else { Diagnostics.Assert( closeSeqNumber == StreamConstants.InitialValueOfLastSequenceNumberInStream || closeSeqNumber > message.MessageSequenceNumber, "{0} received payload message with sequence number {1} which is greater than the close sequence number {2}", this.stream.Tracer, message.MessageSequenceNumber, closeSeqNumber); } var setResultSuccess = this.TrySetResult(message); if (setResultSuccess) { FabricEvents.Events.DataMessageDelivery( "Success::" + this.traceId + "@" + this.stream.TraceType, this.stream.StreamIdentity.ToString(), message.MessageSequenceNumber, this.transactionContext.Id.ToString()); } else { FabricEvents.Events.DataMessageDelivery( "Failure::" + this.traceId + "@" + this.stream.TraceType, this.stream.StreamIdentity.ToString(), message.MessageSequenceNumber, this.transactionContext.Id.ToString()); } }