mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-22 17:47:53 +00:00
Eliminate the NodeHostingModel enum because it isn't extensible. Instead, use extension methods on NodeServicesOptions to configure a NodeInstanceFactory.
This commit is contained in:
@@ -16,7 +16,6 @@ namespace ConsoleApplication
|
|||||||
// Set up the DI system
|
// Set up the DI system
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
services.AddNodeServices(options => {
|
services.AddNodeServices(options => {
|
||||||
options.HostingModel = NodeServicesOptions.DefaultNodeHostingModel;
|
|
||||||
options.ProjectPath = Directory.GetCurrentDirectory();
|
options.ProjectPath = Directory.GetCurrentDirectory();
|
||||||
options.WatchFileExtensions = new string[] {}; // Don't watch anything
|
options.WatchFileExtensions = new string[] {}; // Don't watch anything
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
namespace Microsoft.AspNetCore.NodeServices
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a way of creating and invoking code in a Node.js environment.
|
|
||||||
/// </summary>
|
|
||||||
public enum NodeHostingModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An out-of-process Node.js instance where RPC calls are made via HTTP.
|
|
||||||
/// </summary>
|
|
||||||
Http,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An out-of-process Node.js instance where RPC calls are made over binary sockets.
|
|
||||||
/// </summary>
|
|
||||||
Socket,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNetCore.NodeServices.HostingModels;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.NodeServices
|
namespace Microsoft.AspNetCore.NodeServices
|
||||||
{
|
{
|
||||||
@@ -20,32 +19,7 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
throw new ArgumentNullException(nameof (options));
|
throw new ArgumentNullException(nameof (options));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NodeServicesImpl(() => CreateNodeInstance(options));
|
return new NodeServicesImpl(options.NodeInstanceFactory);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,11 +13,6 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class NodeServicesOptions
|
public class NodeServicesOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Defines the default <see cref="NodeHostingModel"/>.
|
|
||||||
/// </summary>
|
|
||||||
public const NodeHostingModel DefaultNodeHostingModel = NodeHostingModel.Http;
|
|
||||||
|
|
||||||
internal const string TimeoutConfigPropertyName = nameof(InvocationTimeoutMilliseconds);
|
internal const string TimeoutConfigPropertyName = nameof(InvocationTimeoutMilliseconds);
|
||||||
private const int DefaultInvocationTimeoutMilliseconds = 60 * 1000;
|
private const int DefaultInvocationTimeoutMilliseconds = 60 * 1000;
|
||||||
private const string LogCategoryName = "Microsoft.AspNetCore.NodeServices";
|
private const string LogCategoryName = "Microsoft.AspNetCore.NodeServices";
|
||||||
@@ -36,7 +31,6 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
|
|
||||||
EnvironmentVariables = new Dictionary<string, string>();
|
EnvironmentVariables = new Dictionary<string, string>();
|
||||||
InvocationTimeoutMilliseconds = DefaultInvocationTimeoutMilliseconds;
|
InvocationTimeoutMilliseconds = DefaultInvocationTimeoutMilliseconds;
|
||||||
HostingModel = DefaultNodeHostingModel;
|
|
||||||
WatchFileExtensions = (string[])DefaultWatchFileExtensions.Clone();
|
WatchFileExtensions = (string[])DefaultWatchFileExtensions.Clone();
|
||||||
|
|
||||||
// In an ASP.NET environment, we can use the IHostingEnvironment data to auto-populate a few
|
// 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
|
NodeInstanceOutputLogger = loggerFactory != null
|
||||||
? loggerFactory.CreateLogger(LogCategoryName)
|
? loggerFactory.CreateLogger(LogCategoryName)
|
||||||
: new ConsoleLogger(LogCategoryName, null, false);
|
: new ConsoleLogger(LogCategoryName, null, false);
|
||||||
|
|
||||||
|
// By default, we use this package's built-in out-of-process-via-HTTP hosting/transport
|
||||||
|
this.UseHttpHosting();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies which <see cref="NodeHostingModel"/> should be used.
|
/// Specifies how to construct Node.js instances. An <see cref="INodeInstance"/> encapsulates all details about
|
||||||
/// </summary>
|
/// how Node.js instances are launched and communicated with. A new <see cref="INodeInstance"/> will be created
|
||||||
public NodeHostingModel HostingModel { get; set; }
|
/// automatically if the previous instance has terminated (e.g., because a source file changed).
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// If set, this callback function will be invoked to supply the <see cref="INodeServices"/> instance.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<INodeInstance> NodeInstanceFactory { get; set; }
|
public Func<INodeInstance> NodeInstanceFactory { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Serialization;
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
@@ -36,21 +34,19 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
|||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private int _portNumber;
|
private int _portNumber;
|
||||||
|
|
||||||
public HttpNodeInstance(string projectPath, string[] watchFileExtensions, ILogger nodeInstanceOutputLogger,
|
public HttpNodeInstance(NodeServicesOptions options, int port = 0)
|
||||||
IDictionary<string, string> environmentVars, int invocationTimeoutMilliseconds, bool launchWithDebugging,
|
|
||||||
int debuggingPort, int port = 0)
|
|
||||||
: base(
|
: base(
|
||||||
EmbeddedResourceReader.Read(
|
EmbeddedResourceReader.Read(
|
||||||
typeof(HttpNodeInstance),
|
typeof(HttpNodeInstance),
|
||||||
"/Content/Node/entrypoint-http.js"),
|
"/Content/Node/entrypoint-http.js"),
|
||||||
projectPath,
|
options.ProjectPath,
|
||||||
watchFileExtensions,
|
options.WatchFileExtensions,
|
||||||
MakeCommandLineOptions(port),
|
MakeCommandLineOptions(port),
|
||||||
nodeInstanceOutputLogger,
|
options.NodeInstanceOutputLogger,
|
||||||
environmentVars,
|
options.EnvironmentVariables,
|
||||||
invocationTimeoutMilliseconds,
|
options.InvocationTimeoutMilliseconds,
|
||||||
launchWithDebugging,
|
options.LaunchWithDebugging,
|
||||||
debuggingPort)
|
options.DebuggingPort)
|
||||||
{
|
{
|
||||||
_client = new HttpClient();
|
_client = new HttpClient();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods that help with populating a <see cref="NodeServicesOptions"/> object.
|
||||||
|
/// </summary>
|
||||||
|
public static class NodeServicesOptionsExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Configures the <see cref="INodeServices"/> service so that it will use out-of-process
|
||||||
|
/// Node.js instances and perform RPC calls over HTTP.
|
||||||
|
/// </summary>
|
||||||
|
public static void UseHttpHosting(this NodeServicesOptions options)
|
||||||
|
{
|
||||||
|
options.NodeInstanceFactory = () => new HttpNodeInstance(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Configures the <see cref="INodeServices"/> 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).
|
||||||
|
/// </summary>
|
||||||
|
public static void UseSocketHosting(this NodeServicesOptions options)
|
||||||
|
{
|
||||||
|
var pipeName = "pni-" + Guid.NewGuid().ToString("D"); // Arbitrary non-clashing string
|
||||||
|
options.NodeInstanceFactory = () => new SocketNodeInstance(options, pipeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,21 +42,19 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
|
|||||||
private string _socketAddress;
|
private string _socketAddress;
|
||||||
private VirtualConnectionClient _virtualConnectionClient;
|
private VirtualConnectionClient _virtualConnectionClient;
|
||||||
|
|
||||||
public SocketNodeInstance(string projectPath, string[] watchFileExtensions, string socketAddress,
|
public SocketNodeInstance(NodeServicesOptions options, string socketAddress)
|
||||||
ILogger nodeInstanceOutputLogger, IDictionary<string, string> environmentVars,
|
|
||||||
int invocationTimeoutMilliseconds, bool launchWithDebugging, int debuggingPort)
|
|
||||||
: base(
|
: base(
|
||||||
EmbeddedResourceReader.Read(
|
EmbeddedResourceReader.Read(
|
||||||
typeof(SocketNodeInstance),
|
typeof(SocketNodeInstance),
|
||||||
"/Content/Node/entrypoint-socket.js"),
|
"/Content/Node/entrypoint-socket.js"),
|
||||||
projectPath,
|
options.ProjectPath,
|
||||||
watchFileExtensions,
|
options.WatchFileExtensions,
|
||||||
MakeNewCommandLineOptions(socketAddress),
|
MakeNewCommandLineOptions(socketAddress),
|
||||||
nodeInstanceOutputLogger,
|
options.NodeInstanceOutputLogger,
|
||||||
environmentVars,
|
options.EnvironmentVariables,
|
||||||
invocationTimeoutMilliseconds,
|
options.InvocationTimeoutMilliseconds,
|
||||||
launchWithDebugging,
|
options.LaunchWithDebugging,
|
||||||
debuggingPort)
|
options.DebuggingPort)
|
||||||
{
|
{
|
||||||
_socketAddress = socketAddress;
|
_socketAddress = socketAddress;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
return InvokeExportWithPossibleRetryAsync<T>(moduleName, exportedFunctionName, args, /* allowRetry */ true, cancellationToken);
|
return InvokeExportWithPossibleRetryAsync<T>(moduleName, exportedFunctionName, args, /* allowRetry */ true, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
|
private async Task<T> InvokeExportWithPossibleRetryAsync<T>(string moduleName, string exportedFunctionName, object[] args, bool allowRetry, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
ThrowAnyOutstandingDelayedDisposalException();
|
ThrowAnyOutstandingDelayedDisposalException();
|
||||||
var nodeInstance = GetOrCreateCurrentNodeInstance();
|
var nodeInstance = GetOrCreateCurrentNodeInstance();
|
||||||
|
|||||||
Reference in New Issue
Block a user