private async Task<bool> Invoke(MessageResult result, Action<Subscription, object> beforeInvoke, object state) { // Change the state from idle to invoking callback var prevState = Interlocked.CompareExchange(ref _subscriptionState, SubscriptionState.InvokingCallback, SubscriptionState.Idle); if (prevState == SubscriptionState.Disposed) { // Only allow terminal messages after dispose if (!result.Terminal) { return false; } } beforeInvoke(this, state); _counters.MessageBusMessagesReceivedTotal.IncrementBy(result.TotalCount); _counters.MessageBusMessagesReceivedPerSec.IncrementBy(result.TotalCount); try { return await _callback(result, _callbackState); } finally { // Go from invoking callback to idle Interlocked.CompareExchange(ref _subscriptionState, SubscriptionState.Idle, SubscriptionState.InvokingCallback); } }
private Task<bool> TriggerAcks(MessageResult result, object state) { result.Messages.Enumerate<object>(m => m.IsAck, (s, m) => ((IAckHandler)s).TriggerAck(m.CommandId), state: _ackHandler); return TaskAsyncHelper.True; }
public virtual Task<bool> Invoke(MessageResult result) { return Invoke(result, (s, o) => { }, state: null); }
public async Task Work() { // Set the state to working Interlocked.Exchange(ref _state, State.Working); var items = new List<ArraySegment<Message>>(); while (Alive) { int totalCount; object state; items.Clear(); PerformWork(items, out totalCount, out state); if (items.Count > 0) { var messageResult = new MessageResult(items, totalCount); bool result = await Invoke(messageResult, (s, o) => s.BeforeInvoke(o), state); if (!result) { Dispose(); // If the callback said it's done then stop break; } } else { break; } } }