示例#1
0
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException(nameof(envelope));
            }
            if (_clientWebSocket.State != WebSocketState.Open)
            {
                throw new InvalidOperationException("The connection was not initialized. Call OpenAsync first.");
            }

            var envelopeJson = _envelopeSerializer.Serialize(envelope);

            if (_traceWriter != null &&
                _traceWriter.IsEnabled)
            {
                await _traceWriter.TraceAsync(envelopeJson, DataOperation.Send).ConfigureAwait(false);
            }

            var jsonBytes = Encoding.UTF8.GetBytes(envelopeJson);

            await _sendSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            try
            {
                await _clientWebSocket.SendAsync(new ArraySegment <byte>(jsonBytes), WebSocketMessageType.Text, true,
                                                 cancellationToken).ConfigureAwait(false);
            }
            finally
            {
                _sendSemaphore.Release();
            }
        }
示例#2
0
        public async Task ExecuteAsync(IContext context, JObject settings, CancellationToken cancellationToken)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings), $"The settings are required for '{nameof(ProcessCommandAction)}' action");
            }

            string variable = null;

            if (settings.TryGetValue(nameof(variable), out var variableToken))
            {
                variable = variableToken.ToString().Trim('"');
            }

            var command = settings.ToObject <Command>(LimeSerializerContainer.Serializer);

            command.Id = EnvelopeId.NewId();

            var resultCommand = await _sender.ProcessCommandAsync(command, cancellationToken);

            if (string.IsNullOrWhiteSpace(variable))
            {
                return;
            }

            var resultCommandJson = _envelopeSerializer.Serialize(resultCommand);
            await context.SetVariableAsync(variable, resultCommandJson, cancellationToken);
        }
示例#3
0
        /// <summary>
        /// Sends an envelope to
        /// the connected node
        /// </summary>
        /// <param name="envelope">Envelope to be transported</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException("envelope");
            }

            if (_stream == null ||
                !_stream.CanWrite)
            {
                throw new InvalidOperationException("Invalid stream state. Call OpenAsync first.");
            }

            var envelopeJson = _envelopeSerializer.Serialize(envelope);

            if (_traceWriter != null &&
                _traceWriter.IsEnabled)
            {
                await _traceWriter.TraceAsync(envelopeJson, DataOperation.Send).ConfigureAwait(false);
            }

            var jsonBytes = Encoding.UTF8.GetBytes(envelopeJson);
            await _sendSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            try
            {
                await _stream.WriteAsync(jsonBytes, 0, jsonBytes.Length, cancellationToken).ConfigureAwait(false);
            }
            finally
            {
                _sendSemaphore.Release();
            }
        }
        private async Task SendEnvelopeAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            EnsureNotSent();

            await _sendSemaphore.WaitAsync(cancellationToken);

            try
            {
                EnsureNotSent();
                _envelopeSent = true;

                _context.Response.StatusCode  = StatusCodes.Status200OK;
                _context.Response.ContentType = "application/json";
                var serializedEnvelope = _envelopeSerializer.Serialize(envelope);
                var buffer             = ArrayPool <byte> .Shared.Rent(Encoding.UTF8.GetByteCount(serializedEnvelope));

                try
                {
                    var length = Encoding.UTF8.GetBytes(serializedEnvelope, 0, serializedEnvelope.Length, buffer, 0);
                    await _context.Response.Body.WriteAsync(buffer, 0, length, cancellationToken).ConfigureAwait(false);
                }
                finally
                {
                    ArrayPool <byte> .Shared.Return(buffer);
                }
            }
            finally
            {
                _sendSemaphore.Release();
            }
        }
示例#5
0
 private Lazy <string> CreateLazySerializedMessage(IEnvelopeSerializer envelopeSerializer) => new Lazy <string>(() =>
 {
     if (Message != null)
     {
         return(envelopeSerializer.Serialize(Message));
     }
     return(null);
 });
示例#6
0
        public Envelope Send(Envelope envelope, Uri address, IEnvelopeSerializer serializer, IMessageCallback callback = null)
        {
            ITransport transport = null;

            if (_transports.TryGetValue(address.Scheme, out transport))
            {
                var sending = envelope.Clone();

                var channel = TryGetChannel(address);

                // TODO -- look up channel node modifiers if any
                // TODO -- there's a little opportunity here to try to reuse the serialization
                // if you send to more than one channel at a time w/ the same serializer
                if (sending.Data == null || sending.Data.Length == 0)
                {
                    serializer.Serialize(sending, channel);
                }


                sending.AcceptedContentTypes = AcceptedContentTypes.ToArray();
                if (channel != null)
                {
                    sending.Destination = channel.Destination;
                    sending.ReplyUri    = channel.ReplyUri;

                    if (callback == null)
                    {
                        channel.Sender.Send(sending.Data, sending.Headers);
                    }
                    else
                    {
                        callback.Send(sending);
                    }
                }
                else
                {
                    sending.Destination = address;
                    sending.ReplyUri    = transport.DefaultReplyUri();

                    if (callback == null)
                    {
                        transport.Send(sending.Destination, sending.Data, sending.Headers);
                    }
                    else
                    {
                        callback.Send(sending);
                    }
                }

                return(sending);
            }
            else
            {
                throw new InvalidOperationException($"Unrecognized transport scheme '{address.Scheme}'");
            }
        }
示例#7
0
        public LazyInput(
            Message message,
            Identity userIdentity,
            BuilderConfiguration builderConfiguration,
            IDocumentSerializer documentSerializer,
            IEnvelopeSerializer envelopeSerializer,
            IArtificialIntelligenceExtension artificialIntelligenceExtension,
            CancellationToken cancellationToken)
        {
            Message = message ?? throw new ArgumentNullException(nameof(message));
            _builderConfiguration  = builderConfiguration ?? throw new ArgumentNullException(nameof(builderConfiguration));
            _lazySerializedContent = new Lazy <string>(() => documentSerializer.Serialize(Content));
            _analyzable            = new Lazy <bool>(() =>
            {
                string result = null;
                Message?.Metadata?.TryGetValue("builder.analyzable", out result);
                return(result?.ToLower() == "true");
            });
            _lazyAnalyzedContent = new Lazy <Task <AnalysisResponse> >(async() =>
            {
                // Only analyze the input if the type is plain text or analyzable metadata is true.
                if (!_analyzable.Value && Content.GetMediaType() != PlainText.MediaType)
                {
                    return(null);
                }

                try
                {
                    return(await artificialIntelligenceExtension.AnalyzeAsync(
                               new AnalysisRequest
                    {
                        Text = _lazySerializedContent.Value,
                        Extras = new Dictionary <string, string>
                        {
                            ["MessageId"] = Message.Id,
                            ["UserIdentity"] = userIdentity.ToString()
                        }
                    },
                               cancellationToken));
                }
                catch (LimeException)
                {
                    return(null);
                }
            });
            _lazySerializedMessage = new Lazy <string>(() =>
            {
                if (Message != null)
                {
                    return(envelopeSerializer.Serialize(Message));
                }

                return(null);
            });
        }
示例#8
0
        private async Task <string> RequestAsync(string endpoint, Envelope request, CancellationToken cancellationToken)
        {
            using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, $"{MsgingBaseUri}{endpoint}"))
            {
                httpRequestMessage.Content = new StringContent(_envelopeSerializer.Serialize(request), Encoding.UTF8, "application/json");

                using (var httpResponseMessage = await _httpClient.SendAsync(httpRequestMessage, cancellationToken).ConfigureAwait(false))
                {
                    httpResponseMessage.EnsureSuccessStatusCode();
                    return(await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false));
                }
            }
        }
示例#9
0
        /// <summary>
        /// Sends an envelope to the connected node.
        /// </summary>
        /// <param name="envelope">Envelope to be transported</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException(nameof(envelope));
            }
            if (_stream == null)
            {
                throw new InvalidOperationException("The stream was not initialized. Call OpenAsync first.");
            }
            if (!_stream.CanWrite)
            {
                throw new InvalidOperationException("Invalid stream state");
            }

            var serializedEnvelope = _envelopeSerializer.Serialize(envelope);
            int envelopeByteCount  = Encoding.UTF8.GetByteCount(serializedEnvelope);

            if (envelopeByteCount > _maxSenderBufferSize)
            {
                // Prevent sending an envelope that could potentially make the receiver side drop the connection,
                // since most probably it's _maxBufferSize has the same value used by the sender side
                await TraceAsync($"EnvelopeTooLarge (size of {envelopeByteCount}): {serializedEnvelope}", DataOperation.Error).ConfigureAwait(false);

                throw new EnvelopeTooLargeException(
                          $"Envelope NOT sent: {envelope.GetType().Name} with id {envelope.Id} and size {envelopeByteCount} will probably exceed the maximum size supported by a receiver (the local value is {_maxSenderBufferSize})",
                          envelope);
            }

            await TraceAsync(serializedEnvelope, DataOperation.Send).ConfigureAwait(false);

            var buffer = _arrayPool.Rent(envelopeByteCount);
            var length = Encoding.UTF8.GetBytes(serializedEnvelope, 0, serializedEnvelope.Length, buffer, 0);

            try
            {
                await _stream.WriteAsync(buffer, 0, length, cancellationToken).ConfigureAwait(false);
            }
            catch (IOException)
            {
                await CloseWithTimeoutAsync().ConfigureAwait(false);

                throw;
            }
            finally
            {
                _arrayPool.Return(buffer);
            }
        }
示例#10
0
        public static string ExecuteSerialization(IEnvelopeSerializer serializer, Envelope envelope, int count)
        {
            string json = null;

            var sw = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < count; i++)
            {
                json = serializer.Serialize(envelope);
            }
            sw.Stop();

            System.Console.WriteLine("{0}: {1} ms", serializer.GetType().Name, sw.ElapsedMilliseconds);

            return json;
        }
示例#11
0
        public static string ExecuteSerialization(IEnvelopeSerializer serializer, Envelope envelope, int count)
        {
            string json = null;

            var sw = System.Diagnostics.Stopwatch.StartNew();

            for (int i = 0; i < count; i++)
            {
                json = serializer.Serialize(envelope);
            }
            sw.Stop();

            System.Console.WriteLine("{0}: {1} ms", serializer.GetType().Name, sw.ElapsedMilliseconds);

            return(json);
        }
示例#12
0
        public Envelope EnvelopeForSending(Envelope envelope, IEnvelopeSerializer serializer, Uri replyUri)
        {
            var clone = envelope.Clone();

            // Must be done in this order!
            Modifiers.Each(x => x.Modify(clone));
            serializer.Serialize(clone, this);

            clone.Headers[Envelope.DestinationKey] = Uri.ToString();
            clone.Headers[Envelope.ChannelKey]     = Key;

            if (replyUri != null)
            {
                clone.Headers[Envelope.ReplyUriKey] = replyUri.ToString();
            }

            return(clone);
        }
示例#13
0
        public LazyInput(
            Document content,
            IDictionary <string, string> flowConfiguration,
            IDocumentSerializer documentSerializer,
            IEnvelopeSerializer envelopeSerializer,
            IArtificialIntelligenceExtension artificialIntelligenceExtension,
            CancellationToken cancellationToken)
        {
            _flowConfiguration     = flowConfiguration;
            Content                = content;
            _lazySerializedContent = new Lazy <string>(() => documentSerializer.Serialize(content));
            _lazyAnalyzedContent   = new Lazy <Task <AnalysisResponse> >(async() =>
            {
                // Only analyze the input if the type is plain text.
                if (Content.GetMediaType() != PlainText.MediaType)
                {
                    return(null);
                }

                try
                {
                    return(await artificialIntelligenceExtension.AnalyzeAsync(
                               new AnalysisRequest
                    {
                        Text = _lazySerializedContent.Value
                    },
                               cancellationToken));
                }
                catch (LimeException)
                {
                    return(null);
                }
            });
            _lazySerializedMessage = new Lazy <string>(() =>
            {
                var message = EnvelopeReceiverContext <Message> .Envelope;
                if (message != null)
                {
                    return(envelopeSerializer.Serialize(message));
                }

                return(null);
            });
        }
示例#14
0
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException(nameof(envelope));
            }
            if (WebSocket.State != WebSocketState.Open)
            {
                throw new InvalidOperationException("Could not send envelope: websocket is not open");
            }

            var envelopeJson = _envelopeSerializer.Serialize(envelope);

            if (_traceWriter != null &&
                _traceWriter.IsEnabled)
            {
                await _traceWriter.TraceAsync(envelopeJson, DataOperation.Send).ConfigureAwait(false);
            }

            var jsonBytes = Encoding.UTF8.GetBytes(envelopeJson);
            await _sendSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            if (WebSocket.State != WebSocketState.Open)
            {
                throw new InvalidOperationException("Could not send envelope: websocket is not open");
            }

            try
            {
                await WebSocket.SendAsync(new ArraySegment <byte>(jsonBytes), _webSocketMessageType, true,
                                          cancellationToken).ConfigureAwait(false);
            }
            catch (WebSocketException)
            {
                await CloseWithTimeoutAsync().ConfigureAwait(false);

                throw;
            }
            finally
            {
                _sendSemaphore.Release();
            }
        }
示例#15
0
        public LazyInput(
            Message message,
            BuilderConfiguration builderConfiguration,
            IDocumentSerializer documentSerializer,
            IEnvelopeSerializer envelopeSerializer,
            IArtificialIntelligenceExtension artificialIntelligenceExtension,
            CancellationToken cancellationToken)
        {
            Message = message ?? throw new ArgumentNullException(nameof(message));
            _builderConfiguration  = builderConfiguration ?? throw new ArgumentNullException(nameof(builderConfiguration));
            _lazySerializedContent = new Lazy <string>(() => documentSerializer.Serialize(Content));
            _lazyAnalyzedContent   = new Lazy <Task <AnalysisResponse> >(async() =>
            {
                // Only analyze the input if the type is plain text.
                if (Content.GetMediaType() != PlainText.MediaType)
                {
                    return(null);
                }

                try
                {
                    return(await artificialIntelligenceExtension.AnalyzeAsync(
                               new AnalysisRequest
                    {
                        Text = _lazySerializedContent.Value
                    },
                               cancellationToken));
                }
                catch (LimeException)
                {
                    return(null);
                }
            });
            _lazySerializedMessage = new Lazy <string>(() =>
            {
                if (Message != null)
                {
                    return(envelopeSerializer.Serialize(Message));
                }

                return(null);
            });
        }
示例#16
0
        /// <summary>
        /// Writes a envelope into the send pipe.
        /// </summary>
        public async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException(nameof(envelope));
            }
            if (_sendTask == null)
            {
                throw new InvalidOperationException($"The send task was not initialized. Call {nameof(StartAsync)} first.");
            }
            if (_sendTask.IsCompleted)
            {
                throw new InvalidOperationException("Send task is completed");
            }

            var envelopeJson = _envelopeSerializer.Serialize(envelope);

            await TraceAsync(envelopeJson, DataOperation.Send).ConfigureAwait(false);

            // Gets memory from the pipe to write the encoded string.
            // .NET string are UTF16 and the length to UTF8 is usually larger.
            // We can use Encoding.UTF8.GetBytes instead to get the precise length but here this is just a hint and the impact is irrelevant,
            // so we can avoid the overhead.
            var memory = _sendPipe.Writer.GetMemory(envelopeJson.Length);
            var length = Encoding.UTF8.GetBytes(envelopeJson, memory.Span);

            if (_pauseWriterThreshold > 0 &&
                length >= _pauseWriterThreshold)
            {
                throw new InvalidOperationException("Serialized envelope size is larger than pauseWriterThreshold and cannot be sent");
            }

            // Signals the pipe that the data is ready.
            _sendPipe.Writer.Advance(length);

            var flushResult = await _sendPipe.Writer.FlushAsync(cancellationToken).ConfigureAwait(false);

            if (flushResult.IsCompleted || flushResult.IsCanceled)
            {
                throw new InvalidOperationException("Send pipe is completed");
            }
        }
示例#17
0
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            var session = envelope as Session;

            if (session != null &&
                session.State <= SessionState.Established)
            {
                await UpdateReceiveChannelNameAsync(session, cancellationToken);
            }

            var envelopeJson = _envelopeSerializer.Serialize(envelope);

            await _traceWriter.TraceIfEnabledAsync(envelopeJson, DataOperation.Send);

            // Send to the channel or to the server prefix
            await _connectionMultiplexer
            .GetSubscriber()
            .PublishAsync(_sendChannelName ?? GetListenerChannelName(_channelNamespace, ServerChannelPrefix), envelopeJson)
            .ConfigureAwait(false);
        }
        private async Task <Command> RunCommandAsync(Command command)
        {
            var commandString = _envelopeSerializer.Serialize(command);

            using (var httpContent = new StringContent(commandString, Encoding.UTF8, "application/json"))
            {
                try
                {
                    var response = await _client.PostAsync("/commands", httpContent);

                    response.EnsureSuccessStatusCode();
                    var responseBody = await response.Content.ReadAsStringAsync();

                    return((Command)_envelopeSerializer.Deserialize(responseBody));
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Failed to run command");
                    throw ex;
                }
            }
        }
示例#19
0
        /// <summary>
        /// Sends an envelope to the connected node.
        /// </summary>
        /// <param name="envelope">Envelope to be transported</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException(nameof(envelope));
            }
            if (_stream == null)
            {
                throw new InvalidOperationException("The stream was not initialized. Call OpenAsync first.");
            }
            if (!_stream.CanWrite)
            {
                throw new InvalidOperationException("Invalid stream state");
            }

            var envelopeJson = _envelopeSerializer.Serialize(envelope);

            await TraceAsync(envelopeJson, DataOperation.Send).ConfigureAwait(false);

            var jsonBytes = Encoding.UTF8.GetBytes(envelopeJson);

            await _sendSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);

            try
            {
                await _stream.WriteAsync(jsonBytes, 0, jsonBytes.Length, cancellationToken).ConfigureAwait(false);
            }
            catch (IOException)
            {
                await CloseWithTimeoutAsync().ConfigureAwait(false);

                throw;
            }
            finally
            {
                _sendSemaphore.Release();
            }
        }
示例#20
0
        /// <summary>
        /// Sends an envelope to the connected node.
        /// </summary>
        /// <param name="envelope">Envelope to be transported</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            if (envelope == null)
            {
                throw new ArgumentNullException(nameof(envelope));
            }
            if (_stream == null)
            {
                throw new InvalidOperationException("The stream was not initialized. Call OpenAsync first.");
            }
            if (!_stream.CanWrite)
            {
                throw new InvalidOperationException("Invalid stream state");
            }

            var serializedEnvelope = _envelopeSerializer.Serialize(envelope);

            await TraceAsync(serializedEnvelope, DataOperation.Send).ConfigureAwait(false);

            var buffer = _arrayPool.Rent(Encoding.UTF8.GetByteCount(serializedEnvelope));
            var length = Encoding.UTF8.GetBytes(serializedEnvelope, 0, serializedEnvelope.Length, buffer, 0);

            try
            {
                await _stream.WriteAsync(buffer, 0, length, cancellationToken).ConfigureAwait(false);
            }
            catch (IOException)
            {
                await CloseWithTimeoutAsync().ConfigureAwait(false);

                throw;
            }
            finally
            {
                _arrayPool.Return(buffer);
            }
        }
        public override async Task SendAsync(Envelope envelope, CancellationToken cancellationToken)
        {
            EnsureIsConnected();

            await _sendSemaphore.WaitAsync(cancellationToken);

            try
            {
                using (var stream = _webSocket.CreateMessageWriter(WebSocketMessageType.Text))
                {
                    using (var writer = new StreamWriter(stream, Encoding.UTF8))
                    {
                        var envelopeJson = _envelopeSerializer.Serialize(envelope);
                        await TraceDataIfEnabledAsync(envelopeJson, DataOperation.Send).ConfigureAwait(false);

                        await writer.WriteAsync(envelopeJson).ConfigureAwait(false);
                    }
                }
            }
            finally
            {
                _sendSemaphore.Release();
            }
        }
示例#22
0
 private HttpContent GetContent(Envelope envelope) =>
 new StringContent(_serializer.Serialize(envelope), Encoding.UTF8, "application/json");
示例#23
0
        public Envelope EnvelopeForSending(Envelope envelope, IEnvelopeSerializer serializer, Uri replyUri)
        {
            var clone = envelope.Clone();

            // Must be done in this order!
            Modifiers.Each(x => x.Modify(clone));
            serializer.Serialize(clone, this);

            clone.Headers[Envelope.DestinationKey] = Uri.ToString();
            clone.Headers[Envelope.ChannelKey] = Key;

            if (replyUri != null)
            {
                clone.Headers[Envelope.ReplyUriKey] = replyUri.ToString();
            }

            return clone;
        }