private void ProcessResults(MessageResult result) { result.Messages.Enumerate(message => message.IsAck || message.IsCommand, message => { if (message.IsAck) { _ackHandler.TriggerAck(message.CommandId); } else if (message.IsCommand) { var command = _serializer.Parse<Command>(message.Value); ProcessCommand(command); // Only send the ack if this command is waiting for it if (message.WaitForAck) { // If we're on the same box and there's a pending ack for this command then // just trip it if (!_ackHandler.TriggerAck(message.CommandId)) { _bus.Ack(_connectionId, message.Key, message.CommandId).Catch(); } } } }); }
public virtual Task<bool> Invoke(MessageResult result) { return _callback.Invoke(result); }
private PersistentResponse GetResponse(MessageResult result) { // Do a single sweep through the results to process commands and extract values ProcessResults(result); var response = new PersistentResponse(ExcludeMessage) { MessageId = result.LastMessageId, Messages = result.Messages, Disconnect = _disconnected, Aborted = _aborted, TotalCount = result.TotalCount, }; PopulateResponseState(response); _counters.ConnectionMessagesReceivedTotal.IncrementBy(result.TotalCount); _counters.ConnectionMessagesReceivedPerSec.IncrementBy(result.TotalCount); return response; }
private void WorkImpl(TaskCompletionSource<object> taskCompletionSource) { Process: if (!Alive) { // If this subscription is dead then return immediately taskCompletionSource.TrySetResult(null); return; } int totalCount = 0; string nextCursor = null; var items = new List<ArraySegment<Message>>(); object state = null; PerformWork(ref items, out nextCursor, ref totalCount, out state); if (Alive && items.Count > 0) { BeforeInvoke(state); var messageResult = new MessageResult(items, nextCursor, totalCount); Task<bool> callbackTask = Invoke(messageResult); if (callbackTask.IsCompleted) { try { // Make sure exceptions propagate callbackTask.Wait(); if (callbackTask.Result) { // Sync path goto Process; } else { // If we're done pumping messages through to this subscription // then dispose Dispose(); // If the callback said it's done then stop taskCompletionSource.TrySetResult(null); } } catch (Exception ex) { taskCompletionSource.TrySetException(ex); } } else { WorkImplAsync(callbackTask, taskCompletionSource); } } else { taskCompletionSource.TrySetResult(null); } }
private PersistentResponse GetResponse(MessageResult result) { // Do a single sweep through the results to process commands and extract values ProcessResults(result); Debug.Assert(GetCursor != null, "Unable to resolve the cursor since the method is null"); // Resolve the cursor string id = GetCursor(); var response = new PersistentResponse(ExcludeMessage) { MessageId = id, Messages = result.Messages, Disconnect = _disconnected, Aborted = _aborted, TotalCount = result.TotalCount, }; PopulateResponseState(response); _counters.ConnectionMessagesReceivedTotal.IncrementBy(result.TotalCount); _counters.ConnectionMessagesReceivedPerSec.IncrementBy(result.TotalCount); return response; }
public virtual Task <bool> Invoke(MessageResult result) { return(Invoke(result, () => { })); }
private Task<bool> Invoke(MessageResult result, Action beforeInvoke) { // Change the state from idle to invoking callback var state = Interlocked.CompareExchange(ref _subscriptionState, SubscriptionState.InvokingCallback, SubscriptionState.Idle); if (state == SubscriptionState.Disposed) { // Only allow terminal messages after dispose if (!result.Terminal) { return TaskAsyncHelper.False; } } beforeInvoke(); return _callback.Invoke(result).ContinueWith(task => { // Go from invoking callback to idle Interlocked.CompareExchange(ref _subscriptionState, SubscriptionState.Idle, SubscriptionState.InvokingCallback); if (task.IsFaulted) { return TaskAsyncHelper.FromError<bool>(task.Exception); } return TaskAsyncHelper.FromResult(task.Result); }, TaskContinuationOptions.ExecuteSynchronously).FastUnwrap(); }
public virtual Task<bool> Invoke(MessageResult result) { return Invoke(result, () => { }); }