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);
                }
            }
        }
예제 #2
0
        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);
                }
            }
        }
예제 #5
0
 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;
            }
        }