Пример #1
0
        public static IEventHandler UseServiceBusForDurability(
            this object handler,
            ServiceBusSettings settings,
            string handlerCatchupAlias  = null,
            Configuration configuration = null)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            configuration = configuration ?? Configuration.Global;
            var queues  = new Dictionary <Type, QueueClient>();
            var binders = EventHandler.GetBinders(handler);

            // create queues
            var subscriptions = binders.Select(binder => SubscribeToReceiveMessages(binder, handler, settings, configuration, queues))
                                .ToArray();

            configuration.RegisterDisposable(new CompositeDisposable(subscriptions));

            // intercept events for the consequenter and queue them on Service Bus
            var wrappedHandler = handler.WrapAll(SimulatedSend ?? SendMessage(queues));

            return(wrappedHandler);
        }
Пример #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceBusCommandQueueReceiver"/> class.
        /// </summary>
        /// <param name="settings">The service bus settings.</param>
        /// <param name="clockTrigger">The command clockTrigger.</param>
        /// <exception cref="System.ArgumentNullException">
        /// settings
        /// or
        /// clockTrigger
        /// </exception>
        public ServiceBusCommandQueueReceiver(
            ServiceBusSettings settings,
            ISchedulerClockTrigger clockTrigger,
            Func <CommandSchedulerDbContext> createCommandSchedulerDbContext)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }
            if (clockTrigger == null)
            {
                throw new ArgumentNullException("clockTrigger");
            }
            if (createCommandSchedulerDbContext == null)
            {
                throw new ArgumentNullException("createCommandSchedulerDbContext");
            }
            this.settings     = settings;
            this.clockTrigger = clockTrigger;
            this.createCommandSchedulerDbContext = createCommandSchedulerDbContext;

#if DEBUG
            exceptionSubject
            .Where(ex => !(ex is OperationCanceledException))
            .Subscribe(ex => Debug.WriteLine("ServiceBusCommandQueueReceiver error: " + ex));
#endif
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceBusCommandQueueReceiver"/> class.
        /// </summary>
        /// <param name="settings">The service bus settings.</param>
        /// <param name="clockTrigger">The command clockTrigger.</param>
        /// <exception cref="System.ArgumentNullException">
        /// settings
        /// or
        /// clockTrigger
        /// </exception>
        public ServiceBusCommandQueueReceiver(
            ServiceBusSettings settings, 
            ISchedulerClockTrigger clockTrigger, 
            Func<CommandSchedulerDbContext> createCommandSchedulerDbContext)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }
            if (clockTrigger == null)
            {
                throw new ArgumentNullException("clockTrigger");
            }
            if (createCommandSchedulerDbContext == null)
            {
                throw new ArgumentNullException("createCommandSchedulerDbContext");
            }
            this.settings = settings;
            this.clockTrigger = clockTrigger;
            this.createCommandSchedulerDbContext = createCommandSchedulerDbContext;

#if DEBUG
            exceptionSubject
                .Where(ex => !(ex is OperationCanceledException))
                .Subscribe(ex => Debug.WriteLine("ServiceBusCommandQueueReceiver error: " + ex));
#endif
        }
Пример #4
0
        private static void CreateTopicIfDoesNotAlreadyExist(
            this ServiceBusSettings settings,
            TopicDescription topicDescription)
        {
            var namespaceManager = NamespaceManager.CreateFromConnectionString(settings.ConnectionString);

            if (!namespaceManager.TopicExists(topicDescription.Path))
            {
                namespaceManager.CreateTopic(topicDescription);
            }
        }
Пример #5
0
        private static void CreateSubscriptionIfDoesNotAlreadyExist(
            this ServiceBusSettings settings,
            SubscriptionDescription subscriptionDescription)
        {
            var namespaceManager = NamespaceManager.CreateFromConnectionString(settings.ConnectionString);

            if (!namespaceManager.SubscriptionExists(subscriptionDescription.TopicPath, subscriptionDescription.Name))
            {
                namespaceManager.CreateSubscription(subscriptionDescription);
            }
        }
Пример #6
0
        private static void CreateQueueIfDoesNotAlreadyExist(
            this ServiceBusSettings settings,
            QueueDescription queueDescription)
        {
            var namespaceManager = NamespaceManager.CreateFromConnectionString(settings.ConnectionString);

            if (!namespaceManager.QueueExists(queueDescription.Path))
            {
                namespaceManager.CreateQueue(queueDescription);
            }
        }
Пример #7
0
        private static IDisposable SubscribeToReceiveMessages <THandler>(
            IEventHandlerBinder binder,
            THandler handler,
            ServiceBusSettings settings,
            Configuration configuration,
            Dictionary <Type, QueueClient> queues) where THandler : class
        {
            Type eventType = ((dynamic)binder).EventType;

            var queueName = string.Format("{0}_on_{1}.{2}",
                                          EventHandler.Name(handler),
                                          eventType.AggregateTypeForEventType().Name,
                                          eventType.EventName());

            var bus = new InProcessEventBus(errorSubject: (ISubject <EventHandlingError>)configuration.EventBus.Errors);
            var eventBusSubscription = binder.SubscribeToBus(handler, bus);

            var receive = SimulatedReceive;

            if (receive != null)
            {
                var receiveSubscription = receive.Subscribe(e => bus.PublishAsync(e).Subscribe(_ => { }, ex => bus.PublishErrorAsync(new EventHandlingError(ex, @event: e))));
                return(new CompositeDisposable(eventBusSubscription,
                                               receiveSubscription));
            }

            var queueClient = settings.CreateQueueClient(
                queueName,
                settings.ConfigureQueue);

            // starting listening on the queue for incoming events
            queueClient.OnMessage(msg =>
            {
                var storedEvent = msg.GetBody <string>()
                                  .FromJsonTo <StoredEvent>();

                var @event = Serializer.DeserializeEvent(
                    aggregateName: storedEvent.AggregateName,
                    eventName: storedEvent.EventName,
                    body: storedEvent.Body,
                    aggregateId: storedEvent.AggregateId,
                    sequenceNumber: storedEvent.SequenceNumber,
                    timestamp: storedEvent.Timestamp);

                bus.PublishAsync(@event).Subscribe(
                    _ => msg.Complete(),
                    ex => bus.PublishErrorAsync(new EventHandlingError(ex, @event: @event)));
            });

            queues[((dynamic)binder).EventType] = queueClient;

            return(new CompositeDisposable(eventBusSubscription, Disposable.Create(queueClient.Close)));
        }
Пример #8
0
 internal static QueueClient CreateQueueClient(ServiceBusSettings settings)
 {
     return(settings.CreateQueueClient(
                "ScheduledCommands",
                q =>
     {
         q.SupportOrdering = true;
         q.RequiresSession = true;
         q.LockDuration = TimeSpan.FromMinutes(5);
         q.MaxDeliveryCount = (int)(TimeSpan.FromDays(45).Ticks / q.LockDuration.Ticks);
         q.EnableDeadLetteringOnMessageExpiration = false;
     }));
 }
Пример #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceBusCommandQueueSender"/> class.
        /// </summary>
        /// <exception cref="System.ArgumentNullException">queueClient</exception>
        public ServiceBusCommandQueueSender(ServiceBusSettings settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            this.settings = settings;

            MessageDeliveryOffsetFromCommandDueTime = TimeSpan.FromMinutes(2);

#if DEBUG
            exceptionSubject.Subscribe(ex => Debug.WriteLine("ServiceBusCommandQueueSender error: " + ex));
#endif
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceBusCommandQueueSender"/> class.
        /// </summary>
        /// <exception cref="System.ArgumentNullException">queueClient</exception>
        public ServiceBusCommandQueueSender(ServiceBusSettings settings)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            this.settings = settings;

            MessageDeliveryOffsetFromCommandDueTime = TimeSpan.FromMinutes(2);

#if DEBUG
            exceptionSubject.Subscribe(ex => Debug.WriteLine("ServiceBusCommandQueueSender error: " + ex));
#endif
        }
Пример #11
0
        /// <summary>
        ///     Creates a queue client, as well as the target queue if it does not already exist.
        /// </summary>
        public static QueueClient CreateQueueClient(
            this ServiceBusSettings settings,
            string queueName,
            Action <QueueDescription> configure = null)
        {
            queueName = queueName.PrefixedIfConfigured(settings);
            var queueDescription = new QueueDescription(queueName);

            if (configure != null)
            {
                configure(queueDescription);
            }
            settings.CreateQueueIfDoesNotAlreadyExist(queueDescription);
            return(QueueClient.CreateFromConnectionString(settings.ConnectionString, queueName));
        }
Пример #12
0
        /// <summary>
        ///     Creates a topic client, as well as the target topic if it does not already exist.
        /// </summary>
        public static TopicClient CreateTopicClient(
            this ServiceBusSettings settings,
            string topicName,
            Action <TopicDescription> configure = null)
        {
            topicName = topicName.PrefixedIfConfigured(settings);
            var topicDescription = new TopicDescription(topicName);

            if (configure != null)
            {
                configure(topicDescription);
            }
            settings.CreateTopicIfDoesNotAlreadyExist(topicDescription);
            return(TopicClient.CreateFromConnectionString(settings.ConnectionString, topicName));
        }
Пример #13
0
        /// <summary>
        ///     Creates a subscription client, as well as the target subscription if it does not already exist.
        /// </summary>
        public static SubscriptionClient CreateSubscriptionClient(
            this ServiceBusSettings settings,
            string topicPath,
            string subscriptionName,
            Action <SubscriptionDescription> configure = null)
        {
            topicPath = topicPath.PrefixedIfConfigured(settings);
            var subscriptionDescription = new SubscriptionDescription(topicPath, subscriptionName);

            if (configure != null)
            {
                configure(subscriptionDescription);
            }
            settings.CreateSubscriptionIfDoesNotAlreadyExist(subscriptionDescription);
            return(SubscriptionClient.CreateFromConnectionString(settings.ConnectionString, subscriptionDescription.TopicPath, subscriptionDescription.Name));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceBusCommandQueueReceiver"/> class.
        /// </summary>
        /// <param name="settings">The service bus settings.</param>
        /// <param name="scheduler">The command scheduler.</param>
        /// <exception cref="System.ArgumentNullException">
        /// settings
        /// or
        /// scheduler
        /// </exception>
        public ServiceBusCommandQueueReceiver(ServiceBusSettings settings, SqlCommandScheduler scheduler)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler");
            }
            this.settings = settings;
            this.scheduler = scheduler;

#if DEBUG
            exceptionSubject
                .Where(ex => !(ex is OperationCanceledException))
                .Subscribe(ex => Debug.WriteLine("ServiceBusCommandQueueReceiver error: " + ex));
#endif
        }
        public override void SetUp()
        {
            base.SetUp();

            schedulerActivity = new List<IScheduledCommand>();

            using (VirtualClock.Start(DateTimeOffset.Now.AddMonths(1)))
            {
                disposables = new CompositeDisposable();
                Settings.Sources = new ISettingsSource[] { new ConfigDirectorySettings(@"c:\dev\.config") }.Concat(Settings.Sources);

                serviceBusSettings = Settings.Get<ServiceBusSettings>();
                serviceBusSettings.NamePrefix = "itscqrstests";
                serviceBusSettings.ConfigureQueue = q => { q.AutoDeleteOnIdle = TimeSpan.FromMinutes(15); };

                var clockName = Any.Paragraph(4);

                var configuration = new Configuration()
                    .UseSqlEventStore()
                    .UseDependency<GetClockName>(_ => @event => clockName)
                    .UseSqlStorageForScheduledCommands()
                    .AddToCommandSchedulerPipeline<Order>(
                        schedule: async (cmd, next) =>
                        {
                            await next(cmd);
                            schedulerActivity.Add(cmd);
                        },
                        deliver: async (cmd, next) =>
                        {
                            await next(cmd);
                            schedulerActivity.Add(cmd);
                        });

                queueSender = new ServiceBusCommandQueueSender(serviceBusSettings)
                {
                    MessageDeliveryOffsetFromCommandDueTime = TimeSpan.FromSeconds(30)
                };

                disposables.Add(queueSender.Messages.Subscribe(s => Console.WriteLine("[ServiceBusCommandQueueSender] " + s.ToJson())));
                disposables.Add(configuration);
                disposables.Add(ConfigurationContext.Establish(configuration));
            }
        }
Пример #16
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ServiceBusCommandQueueReceiver"/> class.
        /// </summary>
        /// <param name="settings">The service bus settings.</param>
        /// <param name="scheduler">The command scheduler.</param>
        /// <exception cref="System.ArgumentNullException">
        /// settings
        /// or
        /// scheduler
        /// </exception>
        public ServiceBusCommandQueueReceiver(ServiceBusSettings settings, SqlCommandScheduler scheduler)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException("scheduler");
            }
            this.settings  = settings;
            this.scheduler = scheduler;

#if DEBUG
            exceptionSubject
            .Where(ex => !(ex is OperationCanceledException))
            .Subscribe(ex => Debug.WriteLine("ServiceBusCommandQueueReceiver error: " + ex));
#endif
        }
        public override void SetUp()
        {
            base.SetUp();

            using (VirtualClock.Start(DateTimeOffset.Now.AddMonths(1)))
            {
                disposables = new CompositeDisposable();
                Settings.Sources = new ISettingsSource[] { new ConfigDirectorySettings(@"c:\dev\.config") }.Concat(Settings.Sources);

                serviceBusSettings = Settings.Get<ServiceBusSettings>();
                serviceBusSettings.NamePrefix = "itscqrstests";
                serviceBusSettings.ConfigureQueue = q =>
                {
                    q.AutoDeleteOnIdle = TimeSpan.FromMinutes(15);
                };

                bus = new FakeEventBus();
                orderRepository = new SqlEventSourcedRepository<Order>(bus);

                var configuration = new Configuration()
                    .UseSqlEventStore(() => new EventStoreDbContext())
                    .UseEventBus(bus)
                    .UseSqlCommandScheduling()
                    .UseDependency<IEventSourcedRepository<Order>>(t => orderRepository);

                var clockName = Any.Paragraph(4);
                scheduler = new SqlCommandScheduler(configuration) { GetClockName = @event => clockName };

                queueSender = new ServiceBusCommandQueueSender(serviceBusSettings)
                {
                    MessageDeliveryOffsetFromCommandDueTime = TimeSpan.FromSeconds(30)
                };

                disposables.Add(scheduler.Activity.Subscribe(s => Console.WriteLine("SqlCommandScheduler: " + s.ToJson())));
                disposables.Add(queueSender.Messages.Subscribe(s => Console.WriteLine("ServiceBusCommandQueueSender: " + s.ToJson())));
                disposables.Add(bus.Subscribe(scheduler));
                disposables.Add(configuration);
                disposables.Add(ConfigurationContext.Establish(configuration));
            }
        }
 internal static QueueClient CreateQueueClient(ServiceBusSettings settings)
 {
     return settings.CreateQueueClient(
         "ScheduledCommands",
         q =>
         {
             q.SupportOrdering = true;
             q.RequiresSession = true;
             q.LockDuration = TimeSpan.FromMinutes(5);
             q.MaxDeliveryCount = (int) (TimeSpan.FromDays(45).Ticks / q.LockDuration.Ticks);
             q.EnableDeadLetteringOnMessageExpiration = false;
         });
 }
Пример #19
0
 private static string PrefixedIfConfigured(this string name, ServiceBusSettings settings)
 {
     return (string.IsNullOrEmpty(settings.NamePrefix) ? "" : settings.NamePrefix + "_") + name;
 }
Пример #20
0
 private static string PrefixedIfConfigured(this string name, ServiceBusSettings settings)
 {
     return((string.IsNullOrEmpty(settings.NamePrefix) ? "" : settings.NamePrefix + "_") + name);
 }