public Bridge(string leftName, string rightName, bool autoCreateQueues, string autoCreateQueuesIdentity, EndpointInstances endpointInstances, ISubscriptionStorage subscriptionStorage, IDistributionPolicy distributionPolicy, string poisonQueue, Action <TransportExtensions <TLeft> > leftCustomization, Action <TransportExtensions <TRight> > rightCustomization, int?maximumConcurrency) { this.endpointInstances = endpointInstances; this.subscriptionStorage = subscriptionStorage; publishRouter = new PublishRouter(subscriptionStorage, distributionPolicy); sendRouter = new SendRouter(endpointInstances, distributionPolicy); replyRouter = new ReplyRouter(); leftConfig = RawEndpointConfiguration.Create(leftName, (context, _) => Forward(context, rightStartable, rightSubscribeRouter), poisonQueue); var leftTransport = leftConfig.UseTransport <TLeft>(); leftTransport.GetSettings().Set("errorQueue", poisonQueue); leftCustomization?.Invoke(leftTransport); if (autoCreateQueues) { leftConfig.AutoCreateQueue(autoCreateQueuesIdentity); } rightConfig = RawEndpointConfiguration.Create(rightName, (context, _) => Forward(context, leftStartable, leftSubscribeRouter), poisonQueue); var rightTransport = rightConfig.UseTransport <TRight>(); rightTransport.GetSettings().Set("errorQueue", poisonQueue); rightCustomization?.Invoke(rightTransport); if (autoCreateQueues) { rightConfig.AutoCreateQueue(autoCreateQueuesIdentity); } if (maximumConcurrency.HasValue) { leftConfig.LimitMessageProcessingConcurrencyTo(1); rightConfig.LimitMessageProcessingConcurrencyTo(1); } }
static async Task <IRawEndpointInstance> StartMonitor() { var queueMonitorContext = new DefaultMetricsContext("QueueLengthMonitor"); new MetricsConfig(queueMonitorContext) .WithHttpEndpoint("http://localhost:7777/QueueLengthMonitor/") .WithReporting(r => { r.WithReport( new PerformanceCounterReporter(x => new CounterInstanceName("Queue Length", x.MetricName)), TimeSpan.FromSeconds(5), Filter.New.WhereContext(c => c == "QueueLengthMonitor" || c == "QueueState")); }); var monitor = new Monitor(queueMonitorContext, new QueueLength()); var config = RawEndpointConfiguration.Create("QueueLengthMonitor", monitor.OnMessage); config.LimitMessageProcessingConcurrencyTo(1); config.UseTransport <MsmqTransport>(); //config.UseTransport<RabbitMQTransport>().ConnectionString("host=localhost"); config.SendFailedMessagesTo("error"); var endpoint = await RawEndpoint.Start(config); return(endpoint); }
internal static async Task <(IReceivingRawEndpoint, StateStore)> SetupEndpoint(Action <Guid, Message, Message[]> messageProcessed) { var storageTable = await PrepareStorageTable(); var stateStore = new StateStore(storageTable); var handlerInvoker = new HandlerInvoker(stateStore); var endpointConfiguration = RawEndpointConfiguration.Create( endpointName: EndpointName, onMessage: async(c, d) => { var message = Serializer.Deserialize(c.Body, c.Headers); var outputMessages = await handlerInvoker.Process(message); var runId = Guid.Parse(c.Headers["Message.RunId"]); messageProcessed(runId, message, outputMessages); await d.Send(outputMessages, runId); }, poisonMessageQueue: "error"); endpointConfiguration.UseTransport <LearningTransport>() .Transactions(TransportTransactionMode.ReceiveOnly); var defaultFactory = LogManager.Use <DefaultFactory>(); defaultFactory.Level(LogLevel.Debug); var endpoint = await RawEndpoint.Start(endpointConfiguration); return(endpoint, stateStore); }
static async Task Main() { Console.Title = "Case00041163.OccasionalSubscriber"; var endpointConfiguration = RawEndpointConfiguration.Create(Console.Title, (context, messages) => Task.CompletedTask, "error"); endpointConfiguration.UseTransport <MsmqTransport>(); var endpointInstance = await RawEndpoint.Start(endpointConfiguration) .ConfigureAwait(false); var subscriptionMessage = ControlMessageFactory.Create(MessageIntentEnum.Subscribe); subscriptionMessage.Headers[Headers.SubscriptionMessageType] = typeof(MyEvent).AssemblyQualifiedName; subscriptionMessage.Headers[Headers.ReplyToAddress] = "Case00041163.OccasionalSubscriber@FAKEPC"; subscriptionMessage.Headers[Headers.SubscriberTransportAddress] = "Case00041163.OccasionalSubscriber@FAKEPC"; subscriptionMessage.Headers[Headers.SubscriberEndpoint] = "Case00041163.OccasionalSubscriber"; subscriptionMessage.Headers[Headers.TimeSent] = DateTimeExtensions.ToWireFormattedString(DateTime.UtcNow); subscriptionMessage.Headers[Headers.NServiceBusVersion] = "5.6.4"; var operation = new TransportOperation(subscriptionMessage, new UnicastAddressTag("Case00041163.Publisher")); await endpointInstance.Dispatch(new TransportOperations(operation), new TransportTransaction(), new ContextBag()).ConfigureAwait(false); await endpointInstance.Stop().ConfigureAwait(false); }
RawEndpointConfiguration PrepareConfig(string inputQueue, string poisonMessageQueueName, Action <TransportExtensions <T> > transportCustomization, Func <MessageContext, IDispatchMessages, Task> onMessage, PoisonMessageHandling poisonMessageHandling, int?maximumConcurrency, int immediateRetries, int delayedRetries, int circuitBreakerThreshold, bool autoCreateQueue, string autoCreateQueueIdentity) { var circuitBreaker = new RepeatedFailuresCircuitBreaker(inputQueue, circuitBreakerThreshold, e => { logger.Error($"Persistent error while processing messages in {inputQueue}. Entering throttled mode.", e); Task.Run(async() => { await transitionSemaphore.WaitAsync().ConfigureAwait(false); try { var oldEndpoint = endpoint; var throttledConfig = PrepareThrottledConfig(inputQueue, poisonMessageQueueName, transportCustomization, onMessage, poisonMessageHandling, maximumConcurrency, immediateRetries, circuitBreakerThreshold, delayedRetries); var newEndpoint = await RawEndpoint.Start(throttledConfig).ConfigureAwait(false); endpoint = newEndpoint; await oldEndpoint.Stop().ConfigureAwait(false); } catch (Exception ex) { logger.Error("Error when entering throttled mode", ex); } finally { transitionSemaphore.Release(); } }); }); var regularConfig = RawEndpointConfiguration.Create(inputQueue, async(context, dispatcher) => { await onMessage(context, dispatcher).ConfigureAwait(false); circuitBreaker.Success(); }, poisonMessageQueueName); regularConfig.CustomErrorHandlingPolicy(new RegularModePolicy(inputQueue, circuitBreaker, poisonMessageHandling, immediateRetries, delayedRetries)); Task onCriticalError(ICriticalErrorContext context) { logger.Fatal($"The receiver for queue {inputQueue} has encountered a severe error that is likely related to the connectivity with the broker or the broker itself."); return(Task.CompletedTask); } regularConfig.Settings.Set("onCriticalErrorAction", (Func <ICriticalErrorContext, Task>)onCriticalError); var transport = regularConfig.UseTransport <T>(); transportCustomization(transport); if (autoCreateQueue) { regularConfig.AutoCreateQueue(autoCreateQueueIdentity); } if (maximumConcurrency.HasValue) { regularConfig.LimitMessageProcessingConcurrencyTo(maximumConcurrency.Value); } return(regularConfig); }
public RawEndpointConfiguration CreateRawEndpointConfiguration(string name, Func <MessageContext, IDispatchMessages, Task> onMessage, TransportDefinition transportDefinition) { var config = RawEndpointConfiguration.Create(name, onMessage, $"{transportSettings.EndpointName}.Errors"); config.LimitMessageProcessingConcurrencyTo(settings.MaximumConcurrencyLevel); transportCustomization.CustomizeRawEndpoint(config, transportSettings); return(config); }
/// <summary> /// Starts the endpoint. /// </summary> public async Task Start() { var outConfig = RawEndpointConfiguration.Create(storageQueueName, OnOutgoingMessage, poisonMessageQueue); outConfig.LimitMessageProcessingConcurrencyTo(1); transportCustomization(outConfig.UseTransport <T>()); outConfig.CustomErrorHandlingPolicy(new RetryForeverPolicy()); outConfig.AutoCreateQueue(); outEndpoint = await RawEndpoint.Start(outConfig).ConfigureAwait(false); }
static async Task Main(string[] args) { var senderConfig = RawEndpointConfiguration.Create("DummyHandler", OnMessage, "error"); var transport = senderConfig.UseTransport <AzureServiceBusTransport>(); transport.ConnectionString(Environment.GetEnvironmentVariable("AzureServiceBus_ConnectionString")); senderConfig.LimitMessageProcessingConcurrencyTo(10); var sender = await RawEndpoint.Start(senderConfig).ConfigureAwait(false); Console.ReadLine(); }
public override async Task Start(CancellationToken token) { var config = RawEndpointConfiguration.Create("poison", OnMessage, "poison"); config.AutoCreateQueue(); config.CustomErrorHandlingPolicy(new IgnoreErrorsPolicy()); var transport = config.UseTransport <TestTransport>(); transportConfiguration(transport); endpoint = await RawEndpoint.Start(config); }
RawEndpointConfiguration PrepareThrottledConfig(string inputQueue, string poisonMessageQueueName, Action <TransportExtensions <T> > transportCustomization, Func <MessageContext, IDispatchMessages, Task> onMessage, PoisonMessageHandling poisonMessageHandling, int?maximumConcurrency, int immediateRetries, int delayedRetries, int circuitBreakerThreshold) { var switchedBack = false; var throttledConfig = RawEndpointConfiguration.Create(inputQueue, async(context, dispatcher) => { await onMessage(context, dispatcher); if (switchedBack) { return; } await transitionSemaphore.WaitAsync().ConfigureAwait(false); Task.Run(async() => { logger.Info("Exiting throttled mode."); try { var oldEndpoint = endpoint; var regularConfig = PrepareConfig(inputQueue, poisonMessageQueueName, transportCustomization, onMessage, poisonMessageHandling, maximumConcurrency, immediateRetries, delayedRetries, circuitBreakerThreshold, false, null); var newEndpoint = await RawEndpoint.Start(regularConfig).ConfigureAwait(false); endpoint = newEndpoint; await oldEndpoint.Stop().ConfigureAwait(false); } catch (Exception e) { logger.Error("Error when exiting throttled mode", e); } finally { transitionSemaphore.Release(); } }).Ignore(); switchedBack = true; }, poisonMessageQueueName); throttledConfig.CustomErrorHandlingPolicy(new ThrottledModePolicy(inputQueue, immediateRetries)); Task onCriticalError(ICriticalErrorContext context) { logger.Fatal($"The receiver for queue {inputQueue} has encountered a severe error that is likely related to the connectivity with the broker or the broker itself."); return(Task.CompletedTask); } throttledConfig.Settings.Set("onCriticalErrorAction", (Func <ICriticalErrorContext, Task>)onCriticalError); var transport = throttledConfig.UseTransport <T>(); transportCustomization(transport); throttledConfig.LimitMessageProcessingConcurrencyTo(1); return(throttledConfig); }
RawEndpointConfiguration CreateEndpointConfig(KeyValuePair <string, QueueInfo> queueInfo, Task <bool> barrier, string errorQueue) { var config = RawEndpointConfiguration.Create(queueInfo.Value.QueueTable, (context, dispatcher) => OnMessage(context, dispatcher, barrier, queueInfo.Value.Catalogs), errorQueue); var transport = config.UseTransport <SqlServerTransport>() .ConnectionString(queueInfo.Value.ConnectionString) .DefaultSchema(queueInfo.Value.Schema); transport.GetSettings().Set <EndpointInstances>(new EndpointInstances()); config.AutoCreateQueue(); config.DefaultErrorHandlingPolicy(errorQueue, 5); return(config); }
public static async Task InitServerEndpoint(string endpointName) { if (serverEndpoint == null) { var senderConfig = RawEndpointConfiguration.Create( endpointName: endpointName, onMessage: OnMessage, poisonMessageQueue: "error"); senderConfig.UseTransport <MsmqTransport>(); serverEndpoint = await RawEndpoint.Start(senderConfig) .ConfigureAwait(false); } }
public async static Task InitSubTwoEndpoint(string endpointName, Func <MessageContext, IDispatchMessages, Task> func) { if (subscriber2Endpoint == null) { var senderConfig = RawEndpointConfiguration.Create( endpointName: endpointName, onMessage: func, poisonMessageQueue: "error"); senderConfig.UseTransport <MsmqTransport>(); senderConfig.AutoCreateQueue(); subscriber2Endpoint = await RawEndpoint.Start(senderConfig) .ConfigureAwait(false); } }
public Task <ComponentRunner> CreateRunner(RunDescriptor run) { var typedScenarioContext = (TContext)run.ScenarioContext; var sendOnly = onMessage == null; var config = sendOnly ? RawEndpointConfiguration.CreateSendOnly(name) : RawEndpointConfiguration.Create(name, (c, d) => onMessage(c, typedScenarioContext, d), "poison"); config.AutoCreateQueue(); configure(config); return(Task.FromResult <ComponentRunner>(new Runner(config, name, sendOnly, endpoint => onStarting != null ? onStarting(endpoint, typedScenarioContext) : Task.FromResult(0), endpoint => onStarted != null ? onStarted(endpoint, typedScenarioContext) : Task.FromResult(0)))); }
public async Task StartAsync(CancellationToken cancellationToken) { var endpointConfiguration = RawEndpointConfiguration.Create(attribute.QueueName, OnMessage, poisonMessageQueue); if (Directory.Exists(nsbLogPath)) { LogManager.Use <DefaultFactory>().Directory(nsbLogPath); } var connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(attribute.Connection); endpointConfiguration.UseTransport <AzureStorageQueueTransport>().ConnectionString(connectionString); endpointConfiguration.DefaultErrorHandlingPolicy(poisonMessageQueue, immediateRetryCount); endpoint = await RawEndpoint.Start(endpointConfiguration).ConfigureAwait(false); }
static async Task <List <MessageContext> > RunResubscriberOnce(params MessageContext[] input) { await Cleanup("ResubscriberTest", "ResubscriberTest.Resubscriber", "poison").ConfigureAwait(false); var done = new TaskCompletionSource <bool>(); var output = new List <MessageContext>(); var listenerConfig = RawEndpointConfiguration.Create("ResubscriberTest", (context, dispatcher) => { if (context.Headers[Headers.SubscriptionMessageType] == "stop") { done.SetResult(true); } else { output.Add(context); } return(Task.CompletedTask); }, "poison"); listenerConfig.UseTransport <MsmqTransport>(); listenerConfig.LimitMessageProcessingConcurrencyTo(1); listenerConfig.AutoCreateQueue(); var listener = await RawEndpoint.Start(listenerConfig); var resubscriber = await Resubscriber <MsmqTransport> .Create("ResubscriberTest", TimeSpan.FromSeconds(3), t => { }); foreach (var messageContext in input) { await resubscriber.InterceptMessageForwarding("ResubscriberTest", messageContext, NoopDispatch, NoopForward).ConfigureAwait(false); } await resubscriber.InterceptMessageForwarding("ResubscriberTest", CreateTerminatingContext(), NoopDispatch, NoopForward); await resubscriber.Start(); await done.Task; await resubscriber.Stop(); await listener.Stop(); return(output); }
Resubscriber(string inputQueueName, TimeSpan delay, Action <TransportExtensions <T> > configureTransport) { this.inputQueueName = inputQueueName; config = RawEndpointConfiguration.Create(inputQueueName + ".Resubscriber", async(context, dispatcher) => { context.Headers.TryGetValue(Headers.SubscriptionMessageType, out var messageTypeString); if (!context.Headers.TryGetValue(Headers.SubscriberTransportAddress, out var subscriberAddress)) { subscriberAddress = context.Headers[Headers.ReplyToAddress]; } var key = Tuple.Create(subscriberAddress, messageTypeString); var resubscriptionId = context.Headers[ResubscriptionIdHeader]; var resubscriptionTimestamp = DateTime.Parse(context.Headers[ResubscriptionTimestampHeader]); if (idMap.ContainsKey(key)) { var valuePair = idMap[key]; if (valuePair.Item1 != resubscriptionId && resubscriptionTimestamp < valuePair.Item2) { //If we already processed a newer subscribe/unsubscribe message for this -> ignore return; } //We've seen that same message before. Let's pause the resubscription for some time await Task.Delay(delay); } //Send it to the bridge to re-subscribe var outgoingMessage = new OutgoingMessage(context.MessageId, context.Headers, context.Body); var operation = new TransportOperation(outgoingMessage, new UnicastAddressTag(inputQueueName)); await dispatcher.Dispatch(new TransportOperations(operation), context.TransportTransaction, context.Extensions).ConfigureAwait(false); logger.Debug("Moved subscription message back to the queue."); idMap[key] = Tuple.Create(resubscriptionId, resubscriptionTimestamp); }, "poison"); config.AutoCreateQueue(); config.LimitMessageProcessingConcurrencyTo(1); var transport = config.UseTransport <T>(); configureTransport(transport); }
static async Task Start() { #region Configuration var senderConfig = RawEndpointConfiguration.Create( endpointName: "EndpointName", onMessage: OnMessage, poisonMessageQueue: "error"); senderConfig.UseTransport <MsmqTransport>(); var sender = await RawEndpoint.Start(senderConfig) .ConfigureAwait(false); #endregion #region Sending var body = Serialize(); var headers = new Dictionary <string, string> { ["SomeHeader"] = "SomeValue" }; var request = new OutgoingMessage( messageId: Guid.NewGuid().ToString(), headers: headers, body: body); var operation = new TransportOperation( request, new UnicastAddressTag("Receiver")); await sender.SendRaw( outgoingMessages : new TransportOperations(operation), transaction : new TransportTransaction(), context : new ContextBag()) .ConfigureAwait(false); #endregion }
public async Task StartAsync(CancellationToken cancellationToken) { var nameShortener = new RuleNameShortener(); var endpointConfigurationRaw = RawEndpointConfiguration.Create(_attribute.Endpoint, OnMessage, _poisonMessageQueue); if (_nServiceBusOptions.EndpointConfiguration != null) { endpointConfigurationRaw = _nServiceBusOptions.EndpointConfiguration.Invoke(endpointConfigurationRaw); } else { var tokenProvider = TokenProvider.CreateManagedIdentityTokenProvider(); endpointConfigurationRaw.UseTransport <AzureServiceBusTransport>() .RuleNameShortener(nameShortener.Shorten) .CustomTokenProvider(tokenProvider) .ConnectionString(_attribute.Connection) .Transactions(TransportTransactionMode.ReceiveOnly); } if (!string.IsNullOrEmpty(EnvironmentVariables.NServiceBusLicense)) { endpointConfigurationRaw.UseLicense(EnvironmentVariables.NServiceBusLicense); } endpointConfigurationRaw.DefaultErrorHandlingPolicy(_poisonMessageQueue, ImmediateRetryCount); endpointConfigurationRaw.AutoCreateQueue(); _endpoint = await RawEndpoint.Start(endpointConfigurationRaw).ConfigureAwait(false); if (_nServiceBusOptions.OnStarted != null) { _nServiceBusOptions.OnStarted.Invoke(_endpoint); } await _endpoint.SubscriptionManager.Subscribe(_parameter.ParameterType, new ContextBag()); }
public WebOutboxConfiguration(string outboxEndpointName, string destinationEndpointName, string poisonMessageQueue) { _outboxEndpointConfiguration = new EndpointConfiguration(outboxEndpointName); _outboxEndpointConfiguration.Pipeline.Replace( "UnicastSendRouterConnector", new UnicastSendRouterConnector(_unicastRoutingTable, outboxEndpointName), "Routes all messages to the outbox endpoint"); _outboxEndpointConfiguration.Pipeline.Replace( "OutgoingPhysicalToRoutingConnector", new OutgoingPhysicalToRoutingConnector(outboxEndpointName), "Routes all messages to the outbox endpoint"); _outboxEndpointConfiguration.SendOnly(); _forwarderEndpointConfiguration = RawEndpointConfiguration.Create( endpointName: outboxEndpointName, onMessage: (context, messages) => _onMessage?.Invoke(context, messages), poisonMessageQueue: poisonMessageQueue); _destinationEndpointName = destinationEndpointName; _destinationEndpointConfiguration = RawEndpointConfiguration.CreateSendOnly(destinationEndpointName); }
private static async Task Main(string[] args) { var maxConcurrency = 10; var channel = Channel.CreateBounded <MessageContext>(new BoundedChannelOptions(maxConcurrency) { SingleReader = true, SingleWriter = false, AllowSynchronousContinuations = false, FullMode = BoundedChannelFullMode.Wait }); var senderConfig = RawEndpointConfiguration.Create("Sender", (ctx, disp) => OnMessage(ctx, disp, channel), "error"); senderConfig.AutoCreateQueue(); var transport = senderConfig.UseTransport <RabbitMQTransport>(); transport.UseConventionalRoutingTopology(); transport.ConnectionString("host=localhost"); senderConfig.LimitMessageProcessingConcurrencyTo(maxConcurrency); async Task ReadChannel(Channel <MessageContext> channel) { var contexts = new List <MessageContext>(maxConcurrency); await Console.Error.WriteLineAsync("Start reading..."); while (await channel.Reader.WaitToReadAsync().ConfigureAwait(false)) { try { await Console.Error.WriteLineAsync("Start TryRead..."); while (channel.Reader.TryRead(out var context)) { contexts.Add(context); } await Console.Error.WriteLineAsync($"Got pushed {contexts.Count} contexts."); foreach (var context in contexts) { await Console.Error.WriteAsync("."); context.Extensions.Get <TaskCompletionSource <bool> >().TrySetResult(true); } } finally { contexts.Clear(); } await Console.Error.WriteLineAsync("Done TryRead..."); } await Console.Error.WriteLineAsync("Done reading..."); } var readerTask = Task.Run(() => ReadChannel(channel)); var sender = await RawEndpoint.Start(senderConfig).ConfigureAwait(false); var cts = new CancellationTokenSource(); async Task ProduceMessages(IReceivingRawEndpoint sender, CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { var transportOperations = new TransportOperation[15]; for (var i = 0; i < 15; i++) { var headers = new Dictionary <string, string> { ["SomeHeader"] = "SomeValue" }; var request = new OutgoingMessage(Guid.NewGuid().ToString(), headers, Array.Empty <byte>()); transportOperations[i] = new TransportOperation(request, new UnicastAddressTag("Sender")); } await sender.Dispatch( new TransportOperations(transportOperations), //Can have multiple sends in one batch new TransportTransaction(), new ContextBag()) .ConfigureAwait(false); try { await Task.Delay(100, cts.Token); } catch (OperationCanceledException) { // ignored } } await Console.Error.WriteLineAsync("Stopped sending"); } var senderTask = Task.Run(() => ProduceMessages(sender, cts.Token), CancellationToken.None); await Console.Error.WriteLineAsync("Press any key to stop"); await Console.In.ReadLineAsync(); cts.CancelAfter(TimeSpan.FromSeconds(15)); await sender.StopReceiving(); channel.Writer.Complete(); await readerTask; await senderTask; }