Represents a response to a connection.
示例#1
0
        private Task <PersistentResponse> GetResponse(long messageId)
        {
            // Get all messages for the current set of signals
            return(GetMessages(messageId, Signals)
                   .Then <List <Message>, long, PersistentResponse>((messages, id) =>
            {
                if (!messages.Any())
                {
                    // No messages, not even commands
                    return null;
                }

                // Get last message ID
                messageId = messages[messages.Count - 1].Id;

                // Do a single sweep through the results to process commands and extract values
                var messageValues = ProcessResults(messages);

                var response = new PersistentResponse
                {
                    MessageId = messageId,
                    Messages = messageValues,
                    Disconnect = _disconnected
                };

                PopulateResponseState(response);

                return response;
            }, messageId));
        }
示例#2
0
        private Task <PersistentResponse> GetResponse(long messageId)
        {
            // Get all messages for the current set of signals
            return(GetMessages(messageId, Signals)
                   .Success(messageTask =>
            {
                var results = messageTask.Result;
                if (!results.Any())
                {
                    return WaitForSignal(messageId);
                }

                var response = new PersistentResponse();

                var commands = results.Where(m => m.SignalKey.EndsWith(PersistentConnection.SignalrCommand));

                ProcessCommands(commands);

                messageId = results.Max(p => p.Id);

                // Get the message values and the max message id we received
                var messageValues = results.Except(commands)
                                    .Select(m => m.Value)
                                    .ToList();

                response.MessageId = messageId;
                response.Messages = messageValues;

                // Set the groups on the outgoing transport data
                response.TransportData["Groups"] = _groups;

                return TaskAsyncHelper.FromResult(response);
            })
                   .Unwrap());
        }
示例#3
0
        private PersistentResponse GetResponse(MessageResult result)
        {
            // Do a single sweep through the results to process commands and extract values
            var messageValues = ProcessResults(result.Messages);

            var response = new PersistentResponse
            {
                MessageId  = result.LastMessageId,
                Messages   = messageValues,
                Disconnect = _disconnected,
                Aborted    = _aborted,
                TimedOut   = result.TimedOut
            };

            PopulateResponseState(response);

            _trace.Source.TraceInformation("Connection: Connection '{0}' received {1} messages, last id {2}", _connectionId, result.Messages.Count, result.LastMessageId);
            Debug.WriteLine("Connection: Connection '{0}' received {1} messages, last id {2}", _connectionId, result.Messages.Count, result.LastMessageId);
            Debug.WriteLine("Connection: Messages");
            Debug.WriteLine(_serializer.Stringify(result.Messages));
            Debug.WriteLine("Connection: Response");
            Debug.WriteLine(_serializer.Stringify(response));

            return(response);
        }
示例#4
0
        private Task <PersistentResponse> GetResponse(long messageId)
        {
            // Get all messages for the current set of signals
            return(GetMessages(messageId, Signals)
                   .Success(messageTask =>
            {
                var results = messageTask.Result;
                if (!results.Any())
                {
                    return null;
                }

                var response = new PersistentResponse();

                var commands = results.Where(m => m.SignalKey.EndsWith(PersistentConnection.SignalrCommand));

                ProcessCommands(commands);

                messageId = results[results.Count - 1].Id;

                // Get the message values and the max message id we received
                var messageValues = results.Except(commands)
                                    .Select(m => m.Value)
                                    .ToList();

                response.MessageId = messageId;
                response.Messages = messageValues;

                PopulateResponseState(response);

                return response;
            }));
        }
示例#5
0
        public Task <PersistentResponse> ReceiveAsync(string messageId, CancellationToken cancel, int maxMessages)
        {
            var         tcs          = new TaskCompletionSource <PersistentResponse>();
            IDisposable subscription = null;

            const int stateUnassigned = 0;
            const int stateAssigned   = 1;
            const int stateDisposed   = 2;

            int state = stateUnassigned;

            CancellationTokenRegistration registration = cancel.Register(() =>
            {
                // Dispose the subscription only if the handle has been assigned. If not, flag it so that the subscriber knows to Dispose of it for use
                if (Interlocked.Exchange(ref state, stateDisposed) == stateAssigned)
                {
                    subscription.Dispose();
                }
            });

            PersistentResponse response = null;

            subscription = _bus.Subscribe(this, messageId, result =>
            {
                if (Interlocked.CompareExchange(ref response, GetResponse(result), null) == null)
                {
                    registration.Dispose();
                    // Dispose the subscription only if the handle has been assigned. If not, flag it so that the subscriber knows to Dispose of it for use
                    if (Interlocked.Exchange(ref state, stateDisposed) == stateAssigned)
                    {
                        subscription.Dispose();
                    }
                }

                if (result.Terminal)
                {
                    // Use the terminal message id since it's the most accurate
                    // This is important for things like manipulating groups
                    // since the message id is only updated after processing the commands
                    // as part of this call itself.
                    response.MessageId = result.LastMessageId;
                    tcs.TrySetResult(response);

                    return(TaskAsyncHelper.False);
                }

                return(TaskAsyncHelper.True);
            },
                                          maxMessages);

            // If callbacks have already run, they maybe have not been able to Dispose the subscription because the instance was not yet assigned
            if (Interlocked.Exchange(ref state, stateAssigned) == stateDisposed)
            {
                // In this case, we will dispose of it immediately.
                subscription.Dispose();
            }

            return(tcs.Task);
        }
示例#6
0
 private void PopulateResponseState(PersistentResponse response)
 {
     // Set the groups on the outgoing transport data
     if (_groups.Count > 0)
     {
         response.TransportData["Groups"] = _groups.GetSnapshot();
     }
 }
示例#7
0
 private void PopulateResponseState(PersistentResponse response)
 {
     // Set the groups on the outgoing transport data
     if (_groups.Any())
     {
         response.TransportData["Groups"] = _groups;
     }
 }
示例#8
0
        private void SerializePesistentResponse(PersistentResponse response, TextWriter writer)
        {
            var jsonWriter = new JsonTextWriter(writer);

            jsonWriter.WriteStartObject();

            jsonWriter.WritePropertyName("MessageId");
            jsonWriter.WriteValue(response.MessageId);

            jsonWriter.WritePropertyName("Disconnect");
            jsonWriter.WriteValue(response.Disconnect);

            jsonWriter.WritePropertyName("TimedOut");
            jsonWriter.WriteValue(response.TimedOut);

            if (response.TransportData != null)
            {
                jsonWriter.WritePropertyName("TransportData");
                jsonWriter.WriteStartObject();

                object value;
                if (response.TransportData.TryGetValue("Groups", out value))
                {
                    jsonWriter.WritePropertyName("Groups");
                    jsonWriter.WriteStartArray();
                    foreach (var group in (IEnumerable <string>)value)
                    {
                        jsonWriter.WriteValue(group);
                    }
                    jsonWriter.WriteEndArray();
                }

                jsonWriter.WriteEndObject();
            }

            jsonWriter.WritePropertyName("Messages");
            jsonWriter.WriteStartArray();

            for (int i = 0; i < response.Messages.Count; i++)
            {
                ArraySegment <Message> segment = response.Messages[i];
                for (int j = segment.Offset; j < segment.Offset + segment.Count; j++)
                {
                    Message message = segment.Array[j];
                    if (!message.IsCommand)
                    {
                        jsonWriter.WriteRawValue(message.Value);
                    }
                }
            }

            jsonWriter.WriteEndArray();
            jsonWriter.WriteEndObject();
        }
示例#9
0
        private PersistentResponse GetEmptyResponse(long?messageId)
        {
            var response = new PersistentResponse
            {
                MessageId = messageId ?? 0
            };

            PopulateResponseState(response);

            return(response);
        }
示例#10
0
        private PersistentResponse GetEmptyResponse(string messageId, bool timedOut = false)
        {
            var response = new PersistentResponse
            {
                MessageId = messageId,
                TimedOut  = timedOut
            };

            PopulateResponseState(response);

            return(response);
        }
示例#11
0
        private void PopulateResponseState(PersistentResponse response)
        {
            // Set the groups on the outgoing transport data
            if (_groups.Count > 0)
            {
                if (response.TransportData == null)
                {
                    response.TransportData = new Dictionary <string, object>();
                }

                response.TransportData["Groups"] = _groups.GetSnapshot();
            }
        }
示例#12
0
        private Task <PersistentResponse> ProcessSignal(Task <SignalResult> signalTask, long?messageId = null)
        {
            if (signalTask.Result.TimedOut)
            {
                PersistentResponse response = GetEmptyResponse(messageId);

                // Return a task wrapping the result
                return(TaskAsyncHelper.FromResult(response));
            }

            // Get the response for this message id
            return(GetResponse(messageId ?? 0).Success(task => task.Result ?? GetEmptyResponse(messageId)));
        }
示例#13
0
        private Task <PersistentResponse> ProcessSignal(SignalResult result, long?messageId = null)
        {
            if (result.TimedOut)
            {
                PersistentResponse response = GetEmptyResponse(messageId);

                // Return a task wrapping the result
                return(TaskAsyncHelper.FromResult(response));
            }

            // Get the response for this message id
            return(GetResponse(messageId ?? 0)
                   .Then <PersistentResponse, long?>((response, id) => response ?? GetEmptyResponse(id), messageId));
        }
示例#14
0
        public Task <PersistentResponse> ReceiveAsync(string messageId, CancellationToken cancel, int maxMessages)
        {
            var         tcs          = new TaskCompletionSource <PersistentResponse>();
            IDisposable subscription = null;
            var         wh           = new ManualResetEventSlim(initialState: false);

            CancellationTokenRegistration registration = cancel.Register(() =>
            {
                wh.Wait();
                subscription.Dispose();
            });

            PersistentResponse response = null;

            subscription = _bus.Subscribe(this, messageId, result =>
            {
                wh.Wait();

                if (Interlocked.CompareExchange(ref response, GetResponse(result), null) == null)
                {
                    registration.Dispose();
                    subscription.Dispose();
                }

                if (result.Terminal)
                {
                    // Use the terminal message id since it's the most accurate
                    // This is important for things like manipulating groups
                    // since the message id is only updated after processing the commands
                    // as part of this call itself.
                    response.MessageId = result.LastMessageId;
                    tcs.TrySetResult(response);

                    return(TaskAsyncHelper.False);
                }

                return(TaskAsyncHelper.True);
            },
                                          maxMessages);

            // Set this after the subscription is assigned
            wh.Set();

            return(tcs.Task);
        }
示例#15
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
            {
                MessageId  = result.LastMessageId,
                Messages   = result.Messages,
                Disconnect = _disconnected,
                Aborted    = _aborted,
                TotalCount = result.TotalCount
            };

            PopulateResponseState(response);

            return(response);
        }
示例#16
0
        private PersistentResponse GetResponse(MessageResult result)
        {
            // Do a single sweep through the results to process commands and extract values
            var messageValues = ProcessResults(result.Messages);

            var response = new PersistentResponse
            {
                MessageId  = result.LastMessageId,
                Messages   = messageValues,
                Disconnect = _disconnected,
                Aborted    = _aborted
            };

            PopulateResponseState(response);

            Trace.TraceInformation("Connection '{0}' received {1} messages, last id {2}", _connectionId, result.Messages.Count, result.LastMessageId);

            return(response);
        }
示例#17
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);
        }
示例#18
0
        private Task <PersistentResponse> ProcessSignal(Task <SignalResult> signalTask, long?messageId = null)
        {
            if (signalTask.Result.TimedOut)
            {
                // If we timed out waiting for a signal we have a message id then return null
                PersistentResponse response = null;

                // Otherwise ee need to return 0 so that the next request we'll get all messages
                // on the next try
                if (messageId == null)
                {
                    response = new PersistentResponse
                    {
                        MessageId = 0
                    };
                }

                // Return a task wrapping the result
                return(TaskAsyncHelper.FromResult(response));
            }

            // Get the response for this message id
            return(GetResponse(messageId ?? 0));
        }
示例#19
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
            {
                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;
        }
示例#20
0
        private void PopulateResponseState(PersistentResponse response)
        {
            // Set the groups on the outgoing transport data
            if (_groups.Count > 0)
            {
                if (response.TransportData == null)
                {
                    response.TransportData = new Dictionary<string, object>();
                }

                response.TransportData["Groups"] = _groups.GetSnapshot();
            }
        }
示例#21
0
 private void PopulateResponseState(PersistentResponse response)
 {
     // Set the groups on the outgoing transport data
     if (_groups.Count > 0)
     {
         response.TransportData["Groups"] = _groups.GetSnapshot();
     }
 }
示例#22
0
        private PersistentResponse GetResponse(MessageResult result)
        {
            // Do a single sweep through the results to process commands and extract values
            var messageValues = ProcessResults(result.Messages);

            var response = new PersistentResponse
            {
                MessageId = result.LastMessageId,
                Messages = messageValues,
                Disconnect = _disconnected,
                TimedOut = result.TimedOut
            };

            PopulateResponseState(response);

            _trace.Source.TraceInformation("Connection: Connection {0} received {1} messages, last id {2}", _connectionId, result.Messages.Count, result.LastMessageId);

            Debug.WriteLine("Connection: Connection {0} received {1} messages, last id {2}. Payload {3}", _connectionId, result.Messages.Count, result.LastMessageId, _serializer.Stringify(result.Messages));

            return response;
        }
示例#23
0
 private void PopulateResponseState(PersistentResponse response)
 {
     // Set the groups on the outgoing transport data
     if (_groups.Any())
     {
         response.TransportData["Groups"] = _groups;
     }
 }
示例#24
0
        private PersistentResponse GetResponse(MessageResult result)
        {
            // Do a single sweep through the results to process commands and extract values
            var messageValues = ProcessResults(result.Messages);

            var response = new PersistentResponse
            {
                MessageId = result.LastMessageId,
                Messages = messageValues,
                Disconnect = _disconnected,
                Aborted = _aborted
            };

            PopulateResponseState(response);

            Trace.TraceInformation("Connection '{0}' received {1} messages, last id {2}", _connectionId, result.Messages.Count, result.LastMessageId);

            return response;
        }
示例#25
0
        private PersistentResponse GetResponse(MessageResult result)
        {
            // Do a single sweep through the results to process commands and extract values
            var messageValues = ProcessResults(result);

            var response = new PersistentResponse
            {
                MessageId = result.LastMessageId,
                Messages = messageValues,
                Disconnect = _disconnected,
                Aborted = _aborted
            };

            PopulateResponseState(response);

            return response;
        }