Exemple #1
0
        public void Publish(TransportMessage message, PublishOptions publishOptions)
        {
            if (SubscriptionStorage == null)
            {
                throw new InvalidOperationException("Cannot publish on this endpoint - no subscription storage has been configured.");
            }

            var eventTypesToPublish = MessageMetadataRegistry.GetMessageMetadata(publishOptions.EventType.FullName)
                                      .MessageHierarchy
                                      .Distinct()
                                      .ToList();

            var subscribers = SubscriptionStorage.GetSubscriberAddressesForMessage(eventTypesToPublish.Select(t => new MessageType(t))).ToList();

            if (!subscribers.Any())
            {
                PipelineExecutor.CurrentContext.Set("NoSubscribersFoundForMessage", true);
                return;
            }

            PipelineExecutor.CurrentContext.Set("SubscribersForEvent", subscribers);

            foreach (var subscriber in subscribers)
            {
                //this is unicast so we give the message a unique ID
                message.ChangeMessageId(CombGuid.Generate().ToString());

                MessageSender.Send(message, new SendOptions(subscriber)
                {
                    ReplyToAddress = publishOptions.ReplyToAddress,
                    EnforceMessagingBestPractices = publishOptions.EnforceMessagingBestPractices,
                    EnlistInReceiveTransaction    = publishOptions.EnlistInReceiveTransaction,
                });
            }
        }
Exemple #2
0
        public async Task GetSubscriptionResend()
        {
            var subscriptionName = GetStringQueryString("name");

            using (ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context))
                using (context.OpenReadTransaction())
                    await using (var writer = new AsyncBlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        var subscriptionState = Database
                                                .SubscriptionStorage
                                                .GetSubscriptionFromServerStore(subscriptionName);

                        if (subscriptionState == null)
                        {
                            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                            return;
                        }

                        var subscriptionConnections = Database.SubscriptionStorage.GetSubscriptionConnectionsState(context, subscriptionName);
                        var items = SubscriptionStorage.GetResendItems(context, Database.Name, subscriptionState.SubscriptionId);

                        writer.WriteStartObject();
                        writer.WriteArray("Active", subscriptionConnections.GetActiveBatches());
                        writer.WriteComma();
                        writer.WriteArray("Results", items.Select(i => i.ToJson()), context);
                        writer.WriteEndObject();
                    }
        }
        public BusSubscriptionRepository(Uri busUri, SubscriptionStorage storage)
        {
            string uri = busUri.AbsoluteUri;
            if (busUri.Query.Length > 0)
                uri = uri.Replace(busUri.Query, "");

            _busUri = new Uri(uri);
            _storage = storage;
            _fiber = new PoolFiber();
        }
Exemple #4
0
        public async Task CanSnapshotSubscriptionState()
        {
            var(_, leader) = await CreateRaftCluster(1, watcherCluster : true);

            using (var store = GetDocumentStore(options: new Options
            {
                Server = leader
            }))
            {
                var sub = await store.Subscriptions.CreateAsync <User>();

                var worker = store.Subscriptions.GetSubscriptionWorker <User>(sub);

                var waitForBatch = new ManualResetEvent(false);
                var t            = worker.Run((batch) => { waitForBatch.WaitOne(TimeSpan.FromSeconds(15)); });

                using (var session = store.OpenAsyncSession())
                {
                    await session.StoreAsync(new User());

                    await session.SaveChangesAsync();
                }

                var database = await leader.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                database.SubscriptionStorage.GetSubscriptionFromServerStore(sub);


                var server2    = GetNewServer();
                var server2Url = server2.ServerStore.GetNodeHttpServerUrl();
                Servers.Add(server2);

                using (var requestExecutor = ClusterRequestExecutor.CreateForSingleNode(leader.WebUrl, null))
                    using (requestExecutor.ContextPool.AllocateOperationContext(out var ctx))
                    {
                        await requestExecutor.ExecuteAsync(new AddClusterNodeCommand(server2Url, watcher : true), ctx);

                        var addDatabaseNode = new AddDatabaseNodeOperation(store.Database);
                        await store.Maintenance.Server.SendAsync(addDatabaseNode);
                        await WaitAndAssertForValueAsync(() => GetMembersCount(store), 2);
                    }

                database = await server2.ServerStore.DatabasesLandlord.TryGetOrCreateResourceStore(store.Database);

                var state = database.SubscriptionStorage.GetSubscriptionFromServerStore(sub);

                using (server2.ServerStore.Engine.ContextPool.AllocateOperationContext(out ClusterOperationContext context))
                    using (context.OpenReadTransaction())
                    {
                        Assert.Single(SubscriptionStorage.GetResendItems(context, store.Database, state.SubscriptionId));
                    }

                waitForBatch.Set();
            }
        }
Exemple #5
0
        public SubscriptionRouterService Build()
        {
            SubscriptionStorage storage = _subscriptionStorageFactory();

            var repository = new BusSubscriptionRepository(_bus.ControlBus.Endpoint.Address.Uri, storage);

            var service = new SubscriptionRouterService(_bus, repository, _network);

            _observers.Each(x => service.AddObserver(x(_bus, service)));

            return(service);
        }
        public BusSubscriptionRepository(Uri busUri, SubscriptionStorage storage)
        {
            string uri = busUri.AbsoluteUri;

            if (busUri.Query.Length > 0)
            {
                uri = uri.Replace(busUri.Query, "");
            }

            _busUri  = new Uri(uri);
            _storage = storage;
            _fiber   = new PoolFiber();
        }
Exemple #7
0
        /// <summary>
        /// Publishes the given message to all subscribers
        /// </summary>
        /// <param name="message"></param>
        /// <param name="eventTypes"></param>
        /// <returns></returns>
        public bool Publish(TransportMessage message, IEnumerable <Type> eventTypes)
        {
            if (SubscriptionStorage == null)
            {
                throw new InvalidOperationException("Cannot publish on this endpoint - no subscription storage has been configured. Add either 'MsmqSubscriptionStorage()' or 'DbSubscriptionStorage()' after 'NServiceBus.Configure.With()'.");
            }

            var subscribers = Enumerable.ToList <Address>(SubscriptionStorage.GetSubscriberAddressesForMessage(eventTypes.Select(t => new MessageType(t))));

            if (!subscribers.Any())
            {
                return(false);
            }

            foreach (var subscriber in subscribers)
            {
                //this is unicast so we give the message a unique ID
                message.ChangeMessageId(CombGuid.Generate().ToString());

                MessageSender.Send(message, subscriber);
            }

            return(true);
        }
        public void Invoke(IncomingContext context, Action next)
        {
            var transportMessage  = context.PhysicalMessage;
            var messageTypeString = GetSubscriptionMessageTypeFrom(transportMessage);

            var intent = transportMessage.MessageIntent;

            if (string.IsNullOrEmpty(messageTypeString) && intent != MessageIntentEnum.Subscribe && intent != MessageIntentEnum.Unsubscribe)
            {
                next();
                return;
            }

            if (string.IsNullOrEmpty(messageTypeString))
            {
                throw new InvalidOperationException("Message intent is Subscribe, but the subscription message type header is missing!");
            }

            if (intent != MessageIntentEnum.Subscribe && intent != MessageIntentEnum.Unsubscribe)
            {
                throw new InvalidOperationException("Subscription messages need to have intent set to Subscribe/Unsubscribe");
            }

            var subscriberAddress = transportMessage.ReplyToAddress;

            if (subscriberAddress == null || subscriberAddress == Address.Undefined)
            {
                throw new InvalidOperationException("Subscription message arrived without a valid ReplyToAddress");
            }


            if (SubscriptionStorage == null)
            {
                var warning = string.Format("Subscription message from {0} arrived at this endpoint, yet this endpoint is not configured to be a publisher. To avoid this warning make this endpoint a publisher by configuring a subscription storage or using the AsA_Publisher role.", subscriberAddress);
                Logger.WarnFormat(warning);

                if (Debugger.IsAttached)                          // only under debug, so that we don't expose ourselves to a denial of service
                {
                    throw new InvalidOperationException(warning); // and cause message to go to error queue by throwing an exception
                }

                return;
            }

            context.DoNotInvokeAnyMoreHandlers();

            if (transportMessage.MessageIntent == MessageIntentEnum.Subscribe)
            {
                if (!SubscriptionAuthorizer.AuthorizeSubscribe(messageTypeString, subscriberAddress.ToString(), transportMessage.Headers))
                {
                    Logger.Debug(string.Format("Subscription request from {0} on message type {1} was refused.", subscriberAddress, messageTypeString));
                }
                else
                {
                    Logger.Info("Subscribing " + subscriberAddress + " to message type " + messageTypeString);

                    var mt = new MessageType(messageTypeString);

                    SubscriptionStorage.Subscribe(transportMessage.ReplyToAddress, new[]
                    {
                        mt
                    });
                }

                return;
            }


            if (!SubscriptionAuthorizer.AuthorizeUnsubscribe(messageTypeString, subscriberAddress.ToString(), transportMessage.Headers))
            {
                Logger.Debug(string.Format("Unsubscribe request from {0} on message type {1} was refused.", subscriberAddress, messageTypeString));
                return;
            }

            Logger.Info("Unsubscribing " + subscriberAddress + " from message type " + messageTypeString);
            SubscriptionStorage.Unsubscribe(subscriberAddress, new[]
            {
                new MessageType(messageTypeString)
            });
        }
Exemple #9
0
 public void Handle(ListSubscribers message)
 {
     Context.SubscribersOfTheEvent = SubscriptionStorage
                                     .GetSubscriberAddressesForMessage(new[] { new MessageType(typeof(MyEvent)) }).Select(a => a.ToString()).ToList();
     Context.Done = true;
 }
Exemple #10
0
 void SubscribeForNonBrokers(Address address, IEnumerable <Type> eventTypes)
 {
     SubscriptionStorage.Subscribe(address, eventTypes.Select(e => new MessageType(e)));
 }
Exemple #11
0
        public void MutateIncoming(TransportMessage transportMessage)
        {
            string messageTypeString = GetSubscriptionMessageTypeFrom(transportMessage);

            var intent = transportMessage.MessageIntent;

            if (string.IsNullOrEmpty(messageTypeString) && intent != MessageIntentEnum.Subscribe && intent != MessageIntentEnum.Unsubscribe)
            {
                return;
            }

            if (string.IsNullOrEmpty(messageTypeString))
            {
                throw new InvalidOperationException("Message intent is Subscribe, but the subscription message type header is missing!");
            }

            if (intent != MessageIntentEnum.Subscribe && intent != MessageIntentEnum.Unsubscribe)
            {
                throw new InvalidOperationException("Subscription messages need to have intent set to Subscribe/Unsubscribe");
            }

            var subscriberAddress = transportMessage.ReplyToAddress;

            if (subscriberAddress == null || subscriberAddress == Address.Undefined)
            {
                throw new InvalidOperationException("Subscription message arrived without a valid ReplyToAddress");
            }


            if (SubscriptionStorage == null)
            {
                var warning = string.Format("Subscription message from {0} arrived at this endpoint, yet this endpoint is not configured to be a publisher. To avoid this warning make this endpoint a publisher by configuring a subscription storage or using the As_aPublisher role.", subscriberAddress);
                Logger.WarnFormat(warning);

                if (Debugger.IsAttached)                          // only under debug, so that we don't expose ourselves to a denial of service
                {
                    throw new InvalidOperationException(warning); // and cause message to go to error queue by throwing an exception
                }
                return;
            }

            //service locate to avoid a circular dependency
            Builder.Build <IBus>().DoNotContinueDispatchingCurrentMessageToHandlers();

            if (transportMessage.MessageIntent == MessageIntentEnum.Subscribe)
            {
                if (!SubscriptionAuthorizer.AuthorizeSubscribe(messageTypeString, subscriberAddress.ToString(), transportMessage.Headers))
                {
                    Logger.Debug(string.Format("Subscription request from {0} on message type {1} was refused.", subscriberAddress, messageTypeString));
                }
                else
                {
                    Logger.Info("Subscribing " + subscriberAddress + " to message type " + messageTypeString);

                    var mt = new MessageType(messageTypeString);

                    SubscriptionStorage.Subscribe(transportMessage.ReplyToAddress, new[] { mt });
                    if (ClientSubscribed != null)
                    {
                        ClientSubscribed(this, new SubscriptionEventArgs
                        {
                            MessageType             = messageTypeString,
                            SubscriberReturnAddress = subscriberAddress
                        });
                    }
                }

                return;
            }


            if (!SubscriptionAuthorizer.AuthorizeUnsubscribe(messageTypeString, subscriberAddress.ToString(), transportMessage.Headers))
            {
                Logger.Debug(string.Format("Unsubscribe request from {0} on message type {1} was refused.", subscriberAddress, messageTypeString));
                return;
            }

            Logger.Info("Unsubscribing " + subscriberAddress + " from message type " + messageTypeString);
            SubscriptionStorage.Unsubscribe(subscriberAddress, new[] { new MessageType(messageTypeString) });
        }