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, }); } }
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(); }
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(); } }
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(); }
/// <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) }); }
public void Handle(ListSubscribers message) { Context.SubscribersOfTheEvent = SubscriptionStorage .GetSubscriberAddressesForMessage(new[] { new MessageType(typeof(MyEvent)) }).Select(a => a.ToString()).ToList(); Context.Done = true; }
void SubscribeForNonBrokers(Address address, IEnumerable <Type> eventTypes) { SubscriptionStorage.Subscribe(address, eventTypes.Select(e => new MessageType(e))); }
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) }); }