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);
        }
Exemple #2
0
        public EmployeePayrollUpdateCommandHandler(CosmosClient client, IQueueClientFactory clientFactory)
        {
            Guard.Against.Null(client, nameof(client));

            this.client = client;

            queueClient = clientFactory.Create(AppResources.Queue.EmployeePayrollUpdates);
        }
Exemple #3
0
 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;
 }
Exemple #5
0
        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);
        }
Exemple #6
0
        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();
                });
            }));
        }