private async Task HandleUndeliverable(T message) { if (_undeliverableConsumer != null) { var attempts = TryGetAttempts(message); if (_errorConsumer != null) { try { await _undeliverableConsumer.HandleAsync(new QueuedMessage <T> { Attempts = attempts, Message = message }); } catch (Exception e) { await _errorConsumer.HandleAsync(e); } } else { await _undeliverableConsumer.HandleAsync(new QueuedMessage <T> { Attempts = attempts, Message = message }); } Interlocked.Increment(ref _undelivered); if (RetryPolicy != null) { _attempts.Remove(HashMessage(message)); } } }
private async Task HandleBacklog(T message, int attempts) { if (_backlogConsumer != null) { if (_errorConsumer != null) { try { if (!await _backlogConsumer.HandleAsync(new QueuedMessage <T> { Attempts = attempts, Message = message })) { await HandleUndeliverable(message); } } catch (Exception e) { await _errorConsumer.HandleAsync(e); await HandleUndeliverable(message); } } else { if (!await _backlogConsumer.HandleAsync(new QueuedMessage <T> { Attempts = attempts, Message = message })) { await HandleUndeliverable(message); } } } }
private async Task ProductionCycle(ParallelOptions options, T message, ParallelLoopState state) { var attempts = TryGetAttempts(message); if (state.ShouldExitCurrentIteration) { await HandleBacklog(message, attempts); return; } if (_errorConsumer != null) { try { if (!await _consumer.HandleAsync(new QueuedMessage <T> { Attempts = attempts, Message = message })) { await HandleUnsuccessfulDelivery(options, message, state); return; } } catch (Exception e) { await _errorConsumer.HandleAsync(e); await HandleUnsuccessfulDelivery(options, message, state); return; } } else { if (!await _consumer.HandleAsync(new QueuedMessage <T> { Attempts = attempts, Message = message })) { await HandleUnsuccessfulDelivery(options, message, state); return; } } if (RetryPolicy != null) { _attempts.Remove(HashMessage(message)); } Interlocked.Increment(ref _sent); options.CancellationToken.ThrowIfCancellationRequested(); }
public virtual ObservingProducer <T> Produces(IObservable <T> sequence, Action <Exception> onError = null, Action onCompleted = null) { var observer = new ActionObserver <T>(async @event => await _consumer.HandleAsync(@event), onError ?? (exception => { }), onCompleted ?? (() => { })); _cache.Add(observer, sequence); return(this); }
private async Task HandleUndeliverable(T @event) { if (_undeliverableConsumer != null) { await _undeliverableConsumer.HandleAsync(@event); } }
private async Task HandleBacklog(T @event) { if (!await _backlogConsumer.HandleAsync(@event)) { await HandleUndeliverable(@event); } }
public void Produce(Func <T> func, TimeSpan?interval = null) { if (_buffer.IsAddingCompleted) { throw new InvalidOperationException("You cannot subscribe the buffer while stopping"); } func.AsContinuousObservable(interval).Subscribe( onNext: async x => { await Produce(x); }, onError: async e => { if (_errorConsumer != null) { await _errorConsumer?.HandleAsync(e); } }, onCompleted: () => { }, token: _cancel.Token); }
public ActionConsumer(Action <T> @delegate, IConsume <T> forwardTo) { _delegate = async @event => { try { @delegate(@event); return(await forwardTo.HandleAsync(@event)); } catch (Exception) { return(false); } }; }
private async void ProductionCycle(ParallelOptions options, T @event, ParallelLoopState state) { if (state.ShouldExitCurrentIteration) { await HandleBacklog(@event); return; } if (!await _consumer.HandleAsync(@event)) { HandleUnsuccessfulDelivery(options, @event, state); } Interlocked.Increment(ref _sent); options.CancellationToken.ThrowIfCancellationRequested(); }
private static bool Handle <T>(IConsume <T> consumer, T @event) { if (consumer is IConsumeScoped <T> before) { if (!before.Before()) { return(false); } } var result = consumer.HandleAsync(@event).ConfigureAwait(false).GetAwaiter().GetResult(); if (consumer is IConsumeScoped <T> after) { result = after.After(result); } return(result); }
private static bool Handle <T>(IConsume <T> consumer, T @event) { return(consumer.HandleAsync(@event).ConfigureAwait(false).GetAwaiter().GetResult()); }
/// <summary> /// This consumer is invoked when the producer has given up on trying to deliver this message iteration. /// This is the last chance consumer before the message is scrubbed from transient state. /// Keep in mind that nothing stops another process from sending the same message in once it has been /// finalized (sent or undeliverable) at the producer, since the hash is cleared for that message. /// Hence, this provides a best effort "at least once" delivery guarantee, though you are responsible /// for recovering in the event of an undelivery or failure, as the pipeline cannot make guarantees beyond /// only clearing handlers that return true or reach a finalized state. /// </summary> /// <param name="consumer"></param> public void AttachUndeliverable(IConsume <T> consumer) { _undeliverableConsumer = new ActionConsumer <QueuedMessage <T> >(async x => await consumer.HandleAsync(x.Message)); }
/// <summary> /// This consumer is invoked when the producer is stopped immediately or otherwise interrupted, as such on disposal. /// Any messages still waiting to be delivered are flushed to this consumer. If the consumer reports a failure, then /// the /// messages are swept to the undeliverable consumer. /// </summary> public void AttachBacklog(IConsume <T> consumer) { _backlogConsumer = new ActionConsumer <QueuedMessage <T> >(async x => await consumer.HandleAsync(x.Message)); }
private async Task HandleUndeliverable(T @event) { await _undeliverableConsumer.HandleAsync(@event); Interlocked.Increment(ref _undelivered); }