async Task Dispatch(TransportOperations outgoingMessages, IEventStoreConnection connection) { foreach (var op in outgoingMessages.UnicastTransportOperations) { DateTime?dueTime = null; var dueTimeConstraint = op.DeliveryConstraints.OfType <DoNotDeliverBefore>().FirstOrDefault(); var deferConstraint = op.DeliveryConstraints.OfType <DelayDeliveryWith>().FirstOrDefault(); if (dueTimeConstraint != null) { dueTime = dueTimeConstraint.At; } else if (deferConstraint != null) { dueTime = DateTime.UtcNow + deferConstraint.Delay; } if (dueTime != null) { var meta = new MessageMetadata { Destination = op.Destination }; var eventData = ToEventData(op, meta); await timeoutProcessor.Defer(eventData, dueTime.Value, connection).ConfigureAwait(false); } else { await connection.AppendToStreamAsync(op.Destination, ExpectedVersion.Any, ToEventData(op)).ConfigureAwait(false); } } foreach (var op in outgoingMessages.MulticastTransportOperations) { var destinations = await subscriptionManager.GetDestinationQueues(op.MessageType).ConfigureAwait(false); foreach (var destination in destinations) { await connection.AppendToStreamAsync(destination, ExpectedVersion.Any, ToEventData(op)).ConfigureAwait(false); } } }
protected override async Task Terminate(ISubscribeContext context) { var eventMetadata = new MessageMetadata[context.EventTypes.Length]; for (int i = 0; i < context.EventTypes.Length; i++) { eventMetadata[i] = messageMetadataRegistry.GetMessageMetadata(context.EventTypes[i]); } try { await subscriptionManager.SubscribeAll(eventMetadata, context.Extensions, context.CancellationToken).ConfigureAwait(false); } catch (AggregateException e) { if (context.Extensions.TryGet <bool>(MessageSession.SubscribeAllFlagKey, out var flag) && flag) { throw; } // if this is called from Subscribe, rethrow the expected single exception throw e.InnerException ?? e; } }
public async Task Unsubscribe(MessageMetadata eventType, ContextBag context, CancellationToken cancellationToken = default) { var eventDir = GetEventDirectory(eventType.MessageType); var subscriptionEntryPath = GetSubscriptionEntryPath(eventDir); var attempts = 0; // since we have a design that can run into concurrency exceptions we perform a few retries while (true) { cancellationToken.ThrowIfCancellationRequested(); try { if (!File.Exists(subscriptionEntryPath)) { return; } File.Delete(subscriptionEntryPath); return; } catch (IOException) { attempts++; if (attempts > 10) { throw; } //allow the other task to complete await Task.Delay(100, cancellationToken).ConfigureAwait(false); } } }
async Task Subscribe(MessageMetadata eventType, CancellationToken cancellationToken) { var eventDir = GetEventDirectory(eventType.MessageType); // the subscription directory and the subscription information will be created no matter if there's a publisher for the event assuming that the publisher haven’t started yet Directory.CreateDirectory(eventDir); var subscriptionEntryPath = GetSubscriptionEntryPath(eventDir); var attempts = 0; // since we have a design that can run into concurrency exceptions we perform a few retries while (true) { cancellationToken.ThrowIfCancellationRequested(); try { await AsyncFile.WriteText(subscriptionEntryPath, localAddress, cancellationToken).ConfigureAwait(false); return; } catch (IOException) { attempts++; if (attempts > 10) { throw; } //allow the other task to complete await Task.Delay(100, cancellationToken).ConfigureAwait(false); } } }
public InvokeHandlerContext(MessageHandler handler, string messageId, string replyToAddress, Dictionary <string, string> headers, MessageMetadata messageMetadata, object messageBeingHandled, SynchronizedStorageSession storageSession, IBehaviorContext parentContext) : base(messageId, replyToAddress, headers, parentContext) { MessageHandler = handler; Headers = headers; MessageBeingHandled = messageBeingHandled; MessageMetadata = messageMetadata; Set(storageSession); }
protected override async Task Terminate(ISubscribeContext context) { var eventMetadata = new MessageMetadata[context.EventTypes.Length]; for (int i = 0; i < context.EventTypes.Length; i++) { eventMetadata[i] = messageMetadataRegistry.GetMessageMetadata(context.EventTypes[i]); } try { await subscriptionManager.SubscribeAll(eventMetadata, context.Extensions, context.CancellationToken).ConfigureAwait(false); } catch (AggregateException e) { if (context.Extensions.TryGet <bool>(MessageSession.SubscribeAllFlagKey, out var flag) && flag) { throw; } // if this is called from Subscribe, rethrow the expected single exception throw e.InnerException ?? e; } var subscribeTasks = new List <Task>(); foreach (var eventType in context.EventTypes) { try { var publisherAddresses = subscriptionRouter.GetAddressesForEventType(eventType); if (publisherAddresses.Count == 0) { continue; } foreach (var publisherAddress in publisherAddresses) { Logger.Debug($"Subscribing to {eventType.AssemblyQualifiedName} at publisher queue {publisherAddress}"); var subscriptionMessage = ControlMessageFactory.Create(MessageIntentEnum.Subscribe); subscriptionMessage.Headers[Headers.SubscriptionMessageType] = eventType.AssemblyQualifiedName; subscriptionMessage.Headers[Headers.ReplyToAddress] = subscriberAddress; subscriptionMessage.Headers[Headers.SubscriberTransportAddress] = subscriberAddress; subscriptionMessage.Headers[Headers.SubscriberEndpoint] = subscriberEndpoint; subscriptionMessage.Headers[Headers.TimeSent] = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow); subscriptionMessage.Headers[Headers.NServiceBusVersion] = GitVersionInformation.MajorMinorPatch; subscribeTasks.Add(SendSubscribeMessageWithRetries(publisherAddress, subscriptionMessage, eventType.AssemblyQualifiedName, context.Extensions, 0, context.CancellationToken)); } } #pragma warning disable PS0019 // Do not catch Exception without considering OperationCanceledException - Tasks are not observed until below catch (Exception e) #pragma warning restore PS0019 // Do not catch Exception without considering OperationCanceledException { subscribeTasks.Add(Task.FromException(e)); } } var t = Task.WhenAll(subscribeTasks); try { await t.ConfigureAwait(false); } catch (Exception) { // if subscribing via SubscribeAll, throw an AggregateException if (context.Extensions.TryGet <bool>(MessageSession.SubscribeAllFlagKey, out var flag) && flag) { throw t.Exception; } // otherwise throw the first exception to not change exception behavior when calling subscribe. throw; } }