Beispiel #1
0
 /// <summary>
 /// Initializes a new <see cref="MessageJournalEntry"/>
 /// </summary>
 /// <param name="category">The category of journaled message (e.g. sent, received, published)</param>
 /// <param name="position">The position of the message in the journal</param>
 /// <param name="timestamp">The timestamp associated with the journal entry</param>
 /// <param name="data">The message</param>
 public MessageJournalEntry(MessageJournalCategory category, MessageJournalPosition position, DateTime timestamp, Message data)
 {
     Category  = category;
     Position  = position ?? throw new ArgumentNullException(nameof(position));
     Timestamp = timestamp;
     Data      = data ?? throw new ArgumentNullException(nameof(data));
 }
        /// <summary>
        /// Consumes entries from the message journal starting at the specified <paramref name="start"/>
        /// position
        /// </summary>
        /// <param name="start">The position of the first journal entry to consume</param>
        /// <param name="cancellationToken">(Optional) A cancellation token that can be used by the
        /// caller to interrupt the message consumption process</param>
        /// <returns>Returns a task that completes when the end of the journal is reached, when an
        /// exception is thrown, or when cancellation is requested, depending on the options
        /// specified in the constructor</returns>
        private async Task ConsumeAsync(MessageJournalPosition start,
                                        CancellationToken cancellationToken = default(CancellationToken))
        {
            var count   = 0L;
            var bus     = await _bus;
            var current = start ?? await _messageJournal.GetBeginningOfJournal(cancellationToken);

            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    var readResult = await ReadNext(cancellationToken, current);

                    if (readResult != null)
                    {
                        count = await HandleMessageJournalEntries(count, readResult, bus, cancellationToken);

                        current = readResult.Next;
                        if (readResult.EndOfJournal && _haltAtEndOfJournal)
                        {
                            return;
                        }
                    }
                    await Task.Delay(_pollingInterval, cancellationToken);
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
 /// <summary>
 /// Consumes entries from the message journal starting at the specified <paramref name="start"/>
 /// position
 /// </summary>
 /// <param name="start">The position of the first journal entry to consume</param>
 /// <param name="cancellationToken">(Optional) A cancellation token that can be used by the
 /// caller to interrupt the message consumption process</param>
 /// <returns>Returns a task that completes when the end of the journal is reached, when an
 /// exception is thrown, or when cancellation is requested, depending on the options
 /// specified in the constructor</returns>
 public Task Consume(MessageJournalPosition start,
                     CancellationToken cancellationToken = default(CancellationToken))
 {
     return(ConsumeAsync(start, cancellationToken)
            .GetCompletionSource(cancellationToken)
            .Task);
 }
 /// <summary>
 /// Initializes a new <see cref="MessageJournalReadResult"/>
 /// </summary>
 /// <param name="start">The position at which the read started</param>
 /// <param name="next">The next position to read from</param>
 /// <param name="endOfJournal">Whether the end of the journal was reached during the read operation</param>
 /// <param name="messages">The journaled messages that were read</param>
 public MessageJournalReadResult(MessageJournalPosition start, MessageJournalPosition next, bool endOfJournal, IEnumerable <MessageJournalEntry> messages)
 {
     Start        = start ?? throw new ArgumentNullException(nameof(start));
     Next         = next ?? throw new ArgumentNullException(nameof(next));
     EndOfJournal = endOfJournal;
     _entries     = (messages ?? Enumerable.Empty <MessageJournalEntry>()).ToList();
 }
 /// <summary>
 /// Initialies a new <see cref="MessageJournalConsumerProgress"/>
 /// </summary>
 /// <param name="count">The number of entries consumed</param>
 /// <param name="timestamp">The timestamp of the last entry that was read</param>
 /// <param name="current">The position of the message journal entry that was just consumed</param>
 /// <param name="next">The position of the next entry that will be read</param>
 /// <param name="endOfJournal">Whether the entry that was just consumed is the last one in the
 /// journal as of the last read</param>
 public MessageJournalConsumerProgress(long count, DateTime timestamp, MessageJournalPosition current,
                                       MessageJournalPosition next, bool endOfJournal)
 {
     Count        = count;
     Timestamp    = timestamp;
     Current      = current ?? throw new ArgumentNullException(nameof(current));
     Next         = next ?? throw new ArgumentNullException(nameof(next));
     EndOfJournal = endOfJournal;
 }
        private async Task HandleMessageJournalEntry(IBus bus, CancellationToken cancellationToken, MessageJournalEntry current, MessageJournalPosition next, long count)
        {
            try
            {
                // Throws MessageNotAcknowledgedException if there are handling rules that apply to
                // the message but the message is not acknowledged (automatically or otherwise)
                await bus.HandleMessage(current.Data, Thread.CurrentPrincipal, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (MessageNotAcknowledgedException ex)
            {
                _diagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.MessageNotAcknowledged)
                {
                    Message   = current.Data,
                    Detail    = "Message was not acknowledged by any handlers",
                    Exception = ex
                }.Build());

                if (_rethrowExceptions)
                {
                    throw;
                }
            }
            catch (Exception ex)
            {
                _diagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.UnhandledException)
                {
                    Message   = current.Data,
                    Detail    = "Unhandled exception thrown by one or more message handlers",
                    Exception = ex
                }.Build());

                if (_rethrowExceptions)
                {
                    throw;
                }
            }
            finally
            {
                if (_progress != null)
                {
                    var progressReport = new MessageJournalConsumerProgress(
                        count, current.Timestamp, current.Position, next, false);

                    _progress.Report(progressReport);
                }
            }
        }
        private async Task <MessageJournalReadResult> ReadNext(CancellationToken cancellationToken, MessageJournalPosition current)
        {
            MessageJournalReadResult readResult = null;

            try
            {
                readResult = await _messageJournal.Read(current, _batchSize, _filter, cancellationToken);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                _diagnosticService.Emit(new DiagnosticEventBuilder(this, DiagnosticEventType.UnhandledException)
                {
                    Detail    = "Error reading message journal",
                    Exception = ex
                }.Build());

                if (_rethrowExceptions)
                {
                    throw;
                }
            }

            return(readResult);
        }
Beispiel #8
0
 public Task <MessageJournalReadResult> Read(MessageJournalPosition start, int count, MessageJournalFilter filter = null,
                                             CancellationToken cancellationToken = new CancellationToken())
 {
     return(_inner.Read(start, count, filter, cancellationToken));
 }