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}'."); }
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}'."); }