public async Task HandleAsync(IMessage message, Func <Task> handler, string module)
        {
            if (!Enabled)
            {
                _logger.LogWarning("Inbox is disabled, incoming messages won't be processed.");
                return;
            }

            if (message.Id == Guid.Empty)
            {
                // A synchronous request
                await handler();

                return;
            }

            var collection = _database.GetCollection <InboxMessage>($"{module}-module.{_collectionName}");

            _logger.LogTrace($"Received a message with ID: '{message.Id}' to be processed.");
            if (await collection.AsQueryable().AnyAsync(x => x.Id == message.Id))
            {
                _logger.LogWarning($"Message with ID: '{message.Id}' was already processed.");
                return;
            }

            IClientSessionHandle session = null;

            if (_transactionsEnabled)
            {
                session = await _sessionFactory.CreateAsync();

                session.StartTransaction();
            }

            try
            {
                _logger.LogTrace($"Handling a message with ID: '{message.Id}'...");
                await handler();

                await collection.InsertOneAsync(new InboxMessage
                {
                    Id            = message.Id,
                    CorrelationId = message.CorrelationId,
                    Name          = message.GetType().Name.Underscore(),
                    Module        = message.GetModuleName(),
                    Timestamp     = DateTime.UtcNow.ToUnixTimeMilliseconds()
                });

                if (session is {})
                {
                    await session.CommitTransactionAsync();
                }

                _logger.LogTrace($"Handled a message with ID: '{message.Id}'.");
            }
Example #2
0
        public async Task HandleAsync(T @event)
        {
            if (_options.DisableTransactions)
            {
                await TryHandleAsync(@event);

                return;
            }

            using var session = await _sessionFactory.CreateAsync();
            await TryHandleAsync(@event, () => session.CommitTransactionAsync(), () => session.AbortTransactionAsync());
        }
        public async Task HandleAsync(string messageId, Func <Task> handler)
        {
            if (!Enabled)
            {
                _logger.LogWarning("Outbox is disabled, incoming messages won't be processed.");
                return;
            }

            if (string.IsNullOrWhiteSpace(messageId))
            {
                throw new ArgumentException("Message id to be processed cannot be empty.", nameof(messageId));
            }
            // unique check for our message - if messageId already processed we will not call our handler that means we will not involve our command or event handler again
            _logger.LogTrace($"Received a message with id: '{messageId}' to be processed.");
            if (await _inboxRepository.ExistsAsync(m => m.Id == messageId))
            {
                _logger.LogTrace($"Message with id: '{messageId}' was already processed.");
                return;
            }

            IClientSessionHandle session = null;

            if (_transactionsEnabled)
            {
                session = await _sessionFactory.CreateAsync();

                //important thing is here, using a transaction
                session.StartTransaction();
            }

            try
            {
                _logger.LogTrace($"Processing a message with id: '{messageId}'...");
                //we need to store all inbox and outbox data in same transaction and database
                await handler();                                 //outbox pattern - adding outbox event to database here with doing IMessageOutbox.SendAsync in out handler

                await _inboxRepository.AddAsync(new InboxMessage //inbox pattern
                {
                    Id          = messageId,
                    ProcessedAt = DateTime.UtcNow
                });

                if (session is {})
                {
                    await session.CommitTransactionAsync();
                }

                _logger.LogTrace($"Processed a message with id: '{messageId}'.");
            }
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            while (true)
            {
                using var session = _sessionFactory.CreateAsync();
                var messages = await _outbox.GetUnsentAsync();

                var publishTasks = messages.Select(om => _publisher.PublishAsync(om.Message, om.MessageId.ToString()));
                await Task.WhenAll(publishTasks);

                await _outbox.ProcessAsync(messages);

                await Task.Delay(2000, cancellationToken);
            }
        }
        public async Task HandleAsync(string messageId, Func <Task> handler)
        {
            if (!Enabled)
            {
                _logger.LogWarning("Outbox is disabled, incoming messages won't be processed.");
                return;
            }

            if (string.IsNullOrWhiteSpace(messageId))
            {
                throw new ArgumentException("Message id to be processed cannot be empty.", nameof(messageId));
            }

            _logger.LogTrace($"Received a message with id: '{messageId}' to be processed.");
            if (await _inboxRepository.ExistsAsync(m => m.Id == messageId))
            {
                _logger.LogTrace($"Message with id: '{messageId}' was already processed.");
                return;
            }

            IClientSessionHandle session = null;

            if (_transactionsEnabled)
            {
                session = await _sessionFactory.CreateAsync();

                session.StartTransaction();
            }

            try
            {
                _logger.LogTrace($"Processing a message with id: '{messageId}'...");
                await handler();

                await _inboxRepository.AddAsync(new InboxMessage
                {
                    Id          = messageId,
                    ProcessedAt = DateTime.UtcNow
                });

                if (session is {})
                {
                    await session.CommitTransactionAsync();
                }

                _logger.LogTrace($"Processed a message with id: '{messageId}'.");
            }