コード例 #1
0
 protected override Task <T> InvokeExportAsync <T>(
     NodeInvocationInfo invocationInfo,
     CancellationToken cancellationToken)
 {
     return(Task.FromResult <T>(default(T)));
     //throw new NotImplementedException("Use overloaded Invoke method instead");
 }
コード例 #2
0
        protected override async Task <T> InvokeExportAsync <T>(
            NodeInvocationInfo invocationInfo, CancellationToken cancellationToken)
        {
            var payloadJson = JsonConvert.SerializeObject(invocationInfo, jsonSerializerSettings);
            var payload     = new StringContent(payloadJson, Encoding.UTF8, "application/json");
            var watch       = new Stopwatch();

            watch.Start();
            var response = await _client.PostAsync(_endpoint, payload, cancellationToken);

            watch.Stop();
            Trace.WriteLine($"Node call: {watch.ElapsedTicks}");

            if (!response.IsSuccessStatusCode)
            {
                // Unfortunately there's no true way to cancel ReadAsStringAsync calls, hence AbandonIfCancelled
                var responseJson = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);

                var responseError = JsonConvert.DeserializeObject <RpcJsonResponse>(responseJson, jsonSerializerSettings);

                throw new NodeInvocationException(responseError.ErrorMessage, responseError.ErrorDetails);
            }

            var responseContentType = response.Content.Headers.ContentType;

            switch (responseContentType.MediaType)
            {
            case "text/plain":
                // String responses can skip JSON encoding/decoding
                if (typeof(T) != typeof(string))
                {
                    throw new ArgumentException(
                              "Node module responded with non-JSON string. This cannot be converted to the requested generic type: " +
                              typeof(T).FullName);
                }

                var responseString = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);

                return((T)(object)responseString);

            case "application/json":
                var responseJson = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);

                return(JsonConvert.DeserializeObject <T>(responseJson, jsonSerializerSettings));

            case "application/octet-stream":
                // Streamed responses have to be received as System.IO.Stream instances
                if (typeof(T) != typeof(Stream) && typeof(T) != typeof(object))
                {
                    throw new ArgumentException(
                              "Node module responded with binary stream. This cannot be converted to the requested generic type: " +
                              typeof(T).FullName + ". Instead you must use the generic type System.IO.Stream.");
                }

                return((T)(object)(await response.Content.ReadAsStreamAsync().OrThrowOnCancellation(cancellationToken)));

            default:
                throw new InvalidOperationException("Unexpected response content type: " + responseContentType.MediaType);
            }
        }
コード例 #3
0
        protected override async Task <T> InvokeExportAsync <T>(NodeInvocationInfo invocationInfo, CancellationToken cancellationToken)
        {
            if (_connectionHasFailed)
            {
                // _connectionHasFailed implies a protocol-level error. The old instance is no longer of any use.
                var allowConnectionDraining = false;

                // This special exception type forces NodeServicesImpl to restart the Node instance
                throw new NodeInvocationException(
                          "The SocketNodeInstance socket connection failed. See logs to identify the reason.",
                          details: null,
                          nodeInstanceUnavailable: true,
                          allowConnectionDraining: allowConnectionDraining);
            }

            if (_virtualConnectionClient == null)
            {
                // Although we could pass the cancellationToken into EnsureVirtualConnectionClientCreated and
                // have it signal cancellations upstream, that would be a bad thing to do, because all callers
                // wait for the same connection task. There's no reason why the first caller should have the
                // special ability to cancel the connection process in a way that would affect subsequent
                // callers. So, each caller just independently stops awaiting connection if that call is cancelled.
                await ThrowOnCancellation(EnsureVirtualConnectionClientCreated(), cancellationToken);
            }

            // For each invocation, we open a new virtual connection. This gives an API equivalent to opening a new
            // physical connection to the child process, but without the overhead of doing so, because it's really
            // just multiplexed into the existing physical connection stream.
            bool   shouldDisposeVirtualConnection = true;
            Stream virtualConnection = null;

            try
            {
                virtualConnection = _virtualConnectionClient.OpenVirtualConnection();

                // Send request
                WriteJsonLine(virtualConnection, invocationInfo);

                // Determine what kind of response format is expected
                if (typeof(T) == typeof(Stream))
                {
                    // Pass through streamed binary response
                    // It is up to the consumer to dispose this stream, so don't do so here
                    shouldDisposeVirtualConnection = false;
                    return((T)(object)virtualConnection);
                }
                else
                {
                    // Parse and return non-streamed JSON response
                    var response = await ReadJsonAsync <RpcJsonResponse <T> >(virtualConnection, cancellationToken);

                    if (response.ErrorMessage != null)
                    {
                        throw new NodeInvocationException(response.ErrorMessage, response.ErrorDetails);
                    }

                    return(response.Result);
                }
            }
            finally
            {
                if (shouldDisposeVirtualConnection)
                {
                    virtualConnection.Dispose();
                }
            }
        }
コード例 #4
0
 protected override Task <T> InvokeExportAsync <T>(
     NodeInvocationInfo invocationInfo,
     CancellationToken cancellationToken)
 {
     return(Task.FromResult <T>(default(T)));
 }