public void Register(CancellationToken stoppingToken) { IQueueClient client = _factory.Create(); stoppingToken.Register(async() => { _logger.LogInformation("StopListeningAsync"); if (!client.IsClosedOrClosing) { _logger.LogInformation("IQueueClient : close"); await client.CloseAsync(); } }); var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler) { // Maximum number of concurrent calls to the callback ProcessMessagesAsync(), set to 1 for simplicity. // Set it according to how many messages the application wants to process in parallel. MaxConcurrentCalls = 1, // Indicates whether the message pump should automatically complete the messages after returning from user callback. // False below indicates the complete operation is handled by the user callback as in ProcessMessagesAsync(). AutoComplete = false }; client.RegisterMessageHandler((message, cancellationToken) => ProcessMessageAsync(client, message, cancellationToken), messageHandlerOptions); }
public EmployeePayrollUpdateCommandHandler(CosmosClient client, IQueueClientFactory clientFactory) { Guard.Against.Null(client, nameof(client)); this.client = client; queueClient = clientFactory.Create(AppResources.Queue.EmployeePayrollUpdates); }
public SendSmsCommandHandlerWithDelayHandler( ICommandHandlerAsync <SendSmsCommand> handler, IQueueClientFactory queueClientFactory, ILoggerFactory logFactory, ISettingService settingService) { _handler = handler; _queueClient = queueClientFactory.Create <SmsOutgoingMessage>(); _log = logFactory.CreateLogger <SendSmsCommandHandlerWithDelayHandler>(); _settingService = settingService; }
public TriggerSurveyInvitesCommandHandler( IStoreApprenticeSurveyDetails surveyDetailsRepo, ISettingService settingService, IQueueClientFactory queueClientFactory, ILogger <TriggerSurveyInvitesCommandHandler> logger) { _surveyDetailsRepo = surveyDetailsRepo; _settingService = settingService; _queueClient = queueClientFactory.Create <SmsIncomingMessage>(); _logger = logger; }
public async Task EnqueueAsync(IRequest request, CancellationToken cancellationToken = default(CancellationToken)) { if (request == null) { throw new InvalidOperationException($"Request cannot be null"); } var mapperType = _mapperRegistry.GetMapper(request.GetType()); var mapper = _mapperFactory.Create(mapperType); var function = new Func <IRequest, QueueMessage>( (t) => ((dynamic)mapper).ToMessage((dynamic)request)); var message = function.Invoke(request); var client = _clientFactory.Create(); await client.SendAsync(message, cancellationToken); }
public IObservable <IActionableMessage <ICommand> > GetCommandQueueStream(string queueName) { var qc = _queueClientFactory.Create(queueName); return(Observable.Create((IObserver <IActionableMessage <ICommand> > obs) => { var exceptionHandler = new Func <ExceptionReceivedEventArgs, Task>( exceptionArgs => { // TODO: Logging here obs.OnError(exceptionArgs.Exception); return Task.CompletedTask; }); var messageHandlerOptions = new MessageHandlerOptions(exceptionHandler) { MaxConcurrentCalls = 1, AutoComplete = false }; qc.RegisterMessageHandler( async(message, cancellationToken) => { try { var jsonBody = Encoding.UTF8.GetString(message.Body); var jsonObject = JObject.Parse(jsonBody); if (!jsonObject.TryGetValue("type", StringComparison.OrdinalIgnoreCase, out JToken typeToken)) { throw new JsonException("Unable to find the required field [type] on the received command JSON"); } var type = typeToken.Value <string>(); // If we receive a command message that represents a type that we do not recognize, // requeue with the intention of it being consumed by another (maybe newer) client if (!_commandTypeDictionary.TryGetValue(type, out Type commandType)) { // TODO: Logging here // TODO: Potentially properties of message to ensure that it is not received by the same consumer again and again? // TODO: Automatic dead-lettering is configured in CreateQueueIfNotExists() above, but we may want to implement our own logic using message.SystemProperties.DeliveryCount & other props await qc.AbandonAsync(message.SystemProperties.LockToken); return; } var typedCommand = JsonConvert.DeserializeObject(jsonBody, commandType); var messageWrapper = new ServiceBusActionableMessage <ICommand>(qc, message, (ICommand)typedCommand); obs.OnNext(messageWrapper); } catch (Exception ex) { // TODO: Logging here // Note: We purposely do not onError the stream at this point, as deserialization errors // are not a valid reason to kill the entire subscription, and instead should just be dead-lettered await qc.DeadLetterAsync(message.SystemProperties.LockToken, "Failed to deserialize message", ex.Message); } }, messageHandlerOptions); return Disposable.Create( async() => { await qc.CloseAsync(); }); })); }