示例#1
0
        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();
                                                  }
                                              }
                                          }
                                      });
        }
示例#2
0
 public virtual Task<bool> Invoke(MessageResult result)
 {
     return _callback.Invoke(result);
 }
示例#3
0
        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;
        }
示例#4
0
        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);
            }
        }
示例#5
0
        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;
        }
示例#6
0
 public virtual Task <bool> Invoke(MessageResult result)
 {
     return(Invoke(result, () => { }));
 }
示例#7
0
        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();
        }
示例#8
0
 public virtual Task<bool> Invoke(MessageResult result)
 {
     return Invoke(result, () => { });
 }