From ebf5a18344c2ae8f6fd5b40eae8a4cd4da60c33a Mon Sep 17 00:00:00 2001 From: SteveSandersonMS Date: Wed, 30 Nov 2016 11:17:17 +0000 Subject: [PATCH] Eliminate the NodeHostingModel enum because it isn't extensible. Instead, use extension methods on NodeServicesOptions to configure a NodeInstanceFactory. --- samples/misc/LatencyTest/Program.cs | 1 - .../Configuration/NodeHostingModel.cs | 18 ----------- .../Configuration/NodeServicesFactory.cs | 28 +---------------- .../Configuration/NodeServicesOptions.cs | 18 ++++------- .../HostingModels/HttpNodeInstance.cs | 20 +++++-------- .../NodeServicesOptionsExtensions.cs | 30 +++++++++++++++++++ .../HostingModels/SocketNodeInstance.cs | 18 +++++------ .../NodeServicesImpl.cs | 2 +- 8 files changed, 54 insertions(+), 81 deletions(-) delete mode 100644 src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs create mode 100644 src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeServicesOptionsExtensions.cs diff --git a/samples/misc/LatencyTest/Program.cs b/samples/misc/LatencyTest/Program.cs index e435d37..6efd75f 100755 --- a/samples/misc/LatencyTest/Program.cs +++ b/samples/misc/LatencyTest/Program.cs @@ -16,7 +16,6 @@ namespace ConsoleApplication // Set up the DI system var services = new ServiceCollection(); services.AddNodeServices(options => { - options.HostingModel = NodeServicesOptions.DefaultNodeHostingModel; options.ProjectPath = Directory.GetCurrentDirectory(); options.WatchFileExtensions = new string[] {}; // Don't watch anything }); diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs deleted file mode 100644 index a1c9c12..0000000 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeHostingModel.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Microsoft.AspNetCore.NodeServices -{ - /// - /// Represents a way of creating and invoking code in a Node.js environment. - /// - public enum NodeHostingModel - { - /// - /// An out-of-process Node.js instance where RPC calls are made via HTTP. - /// - Http, - - /// - /// An out-of-process Node.js instance where RPC calls are made over binary sockets. - /// - Socket, - } -} diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs index 73db500..8432158 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesFactory.cs @@ -1,5 +1,4 @@ using System; -using Microsoft.AspNetCore.NodeServices.HostingModels; namespace Microsoft.AspNetCore.NodeServices { @@ -19,33 +18,8 @@ namespace Microsoft.AspNetCore.NodeServices { throw new ArgumentNullException(nameof (options)); } - - return new NodeServicesImpl(() => CreateNodeInstance(options)); - } - private static INodeInstance CreateNodeInstance(NodeServicesOptions options) - { - if (options.NodeInstanceFactory != null) - { - // If you've explicitly supplied an INodeInstance factory, we'll use that. This is useful for - // custom INodeInstance implementations. - return options.NodeInstanceFactory(); - } - else - { - switch (options.HostingModel) - { - case NodeHostingModel.Http: - return new HttpNodeInstance(options.ProjectPath, options.WatchFileExtensions, options.NodeInstanceOutputLogger, - options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort, /* port */ 0); - case NodeHostingModel.Socket: - var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string - return new SocketNodeInstance(options.ProjectPath, options.WatchFileExtensions, pipeName, options.NodeInstanceOutputLogger, - options.EnvironmentVariables, options.InvocationTimeoutMilliseconds, options.LaunchWithDebugging, options.DebuggingPort); - default: - throw new ArgumentException("Unknown hosting model: " + options.HostingModel); - } - } + return new NodeServicesImpl(options.NodeInstanceFactory); } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs index 5324f13..43d703b 100644 --- a/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs +++ b/src/Microsoft.AspNetCore.NodeServices/Configuration/NodeServicesOptions.cs @@ -13,11 +13,6 @@ namespace Microsoft.AspNetCore.NodeServices /// public class NodeServicesOptions { - /// - /// Defines the default . - /// - public const NodeHostingModel DefaultNodeHostingModel = NodeHostingModel.Http; - internal const string TimeoutConfigPropertyName = nameof(InvocationTimeoutMilliseconds); private const int DefaultInvocationTimeoutMilliseconds = 60 * 1000; private const string LogCategoryName = "Microsoft.AspNetCore.NodeServices"; @@ -36,7 +31,6 @@ namespace Microsoft.AspNetCore.NodeServices EnvironmentVariables = new Dictionary(); InvocationTimeoutMilliseconds = DefaultInvocationTimeoutMilliseconds; - HostingModel = DefaultNodeHostingModel; WatchFileExtensions = (string[])DefaultWatchFileExtensions.Clone(); // In an ASP.NET environment, we can use the IHostingEnvironment data to auto-populate a few @@ -53,15 +47,15 @@ namespace Microsoft.AspNetCore.NodeServices NodeInstanceOutputLogger = loggerFactory != null ? loggerFactory.CreateLogger(LogCategoryName) : new ConsoleLogger(LogCategoryName, null, false); + + // By default, we use this package's built-in out-of-process-via-HTTP hosting/transport + this.UseHttpHosting(); } /// - /// Specifies which should be used. - /// - public NodeHostingModel HostingModel { get; set; } - - /// - /// If set, this callback function will be invoked to supply the instance. + /// Specifies how to construct Node.js instances. An encapsulates all details about + /// how Node.js instances are launched and communicated with. A new will be created + /// automatically if the previous instance has terminated (e.g., because a source file changed). /// public Func NodeInstanceFactory { get; set; } diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs index 1ab4c13..77bab1a 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs @@ -1,12 +1,10 @@ using System; -using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; @@ -36,21 +34,19 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels private bool _disposed; private int _portNumber; - public HttpNodeInstance(string projectPath, string[] watchFileExtensions, ILogger nodeInstanceOutputLogger, - IDictionary environmentVars, int invocationTimeoutMilliseconds, bool launchWithDebugging, - int debuggingPort, int port = 0) + public HttpNodeInstance(NodeServicesOptions options, int port = 0) : base( EmbeddedResourceReader.Read( typeof(HttpNodeInstance), "/Content/Node/entrypoint-http.js"), - projectPath, - watchFileExtensions, + options.ProjectPath, + options.WatchFileExtensions, MakeCommandLineOptions(port), - nodeInstanceOutputLogger, - environmentVars, - invocationTimeoutMilliseconds, - launchWithDebugging, - debuggingPort) + options.NodeInstanceOutputLogger, + options.EnvironmentVariables, + options.InvocationTimeoutMilliseconds, + options.LaunchWithDebugging, + options.DebuggingPort) { _client = new HttpClient(); } diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeServicesOptionsExtensions.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeServicesOptionsExtensions.cs new file mode 100644 index 0000000..945c8db --- /dev/null +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/NodeServicesOptionsExtensions.cs @@ -0,0 +1,30 @@ +using System; + +namespace Microsoft.AspNetCore.NodeServices.HostingModels +{ + /// + /// Extension methods that help with populating a object. + /// + public static class NodeServicesOptionsExtensions + { + /// + /// Configures the service so that it will use out-of-process + /// Node.js instances and perform RPC calls over HTTP. + /// + public static void UseHttpHosting(this NodeServicesOptions options) + { + options.NodeInstanceFactory = () => new HttpNodeInstance(options); + } + + /// + /// Configures the service so that it will use out-of-process + /// Node.js instances and perform RPC calls over binary sockets (on Windows, this is + /// implemented as named pipes; on other platforms it uses domain sockets). + /// + public static void UseSocketHosting(this NodeServicesOptions options) + { + var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string + options.NodeInstanceFactory = () => new SocketNodeInstance(options, pipeName); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.NodeServices/HostingModels/SocketNodeInstance.cs b/src/Microsoft.AspNetCore.NodeServices/HostingModels/SocketNodeInstance.cs index 5eabab9..190da85 100644 --- a/src/Microsoft.AspNetCore.NodeServices/HostingModels/SocketNodeInstance.cs +++ b/src/Microsoft.AspNetCore.NodeServices/HostingModels/SocketNodeInstance.cs @@ -42,21 +42,19 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels private string _socketAddress; private VirtualConnectionClient _virtualConnectionClient; - public SocketNodeInstance(string projectPath, string[] watchFileExtensions, string socketAddress, - ILogger nodeInstanceOutputLogger, IDictionary environmentVars, - int invocationTimeoutMilliseconds, bool launchWithDebugging, int debuggingPort) + public SocketNodeInstance(NodeServicesOptions options, string socketAddress) : base( EmbeddedResourceReader.Read( typeof(SocketNodeInstance), "/Content/Node/entrypoint-socket.js"), - projectPath, - watchFileExtensions, + options.ProjectPath, + options.WatchFileExtensions, MakeNewCommandLineOptions(socketAddress), - nodeInstanceOutputLogger, - environmentVars, - invocationTimeoutMilliseconds, - launchWithDebugging, - debuggingPort) + options.NodeInstanceOutputLogger, + options.EnvironmentVariables, + options.InvocationTimeoutMilliseconds, + options.LaunchWithDebugging, + options.DebuggingPort) { _socketAddress = socketAddress; } diff --git a/src/Microsoft.AspNetCore.NodeServices/NodeServicesImpl.cs b/src/Microsoft.AspNetCore.NodeServices/NodeServicesImpl.cs index 38d3055..cc68448 100644 --- a/src/Microsoft.AspNetCore.NodeServices/NodeServicesImpl.cs +++ b/src/Microsoft.AspNetCore.NodeServices/NodeServicesImpl.cs @@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.NodeServices return InvokeExportWithPossibleRetryAsync(moduleName, exportedFunctionName, args, /* allowRetry */ true, cancellationToken); } - public async Task InvokeExportWithPossibleRetryAsync(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken) + private async Task InvokeExportWithPossibleRetryAsync(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken) { ThrowAnyOutstandingDelayedDisposalException(); var nodeInstance = GetOrCreateCurrentNodeInstance();