mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-22 17:47:53 +00:00
Support streamed response from SocketNodeInstance
This commit is contained in:
@@ -78,14 +78,29 @@
|
|||||||
var invocation = JSON.parse(line);
|
var invocation = JSON.parse(line);
|
||||||
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
var invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
||||||
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
var invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
||||||
// Actually invoke it, passing the callback followed by any supplied args
|
// Prepare a callback for accepting non-streamed JSON responses
|
||||||
|
var hasInvokedCallback_1 = false;
|
||||||
var invocationCallback = function (errorValue, successValue) {
|
var invocationCallback = function (errorValue, successValue) {
|
||||||
|
if (hasInvokedCallback_1) {
|
||||||
|
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
|
||||||
|
+ ' or the result stream has already been accessed');
|
||||||
|
}
|
||||||
|
hasInvokedCallback_1 = true;
|
||||||
connection.end(JSON.stringify({
|
connection.end(JSON.stringify({
|
||||||
result: successValue,
|
result: successValue,
|
||||||
errorMessage: errorValue && (errorValue.message || errorValue),
|
errorMessage: errorValue && (errorValue.message || errorValue),
|
||||||
errorDetails: errorValue && (errorValue.stack || null)
|
errorDetails: errorValue && (errorValue.stack || null)
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
// Also support streamed binary responses
|
||||||
|
Object.defineProperty(invocationCallback, 'stream', {
|
||||||
|
enumerable: true,
|
||||||
|
get: function () {
|
||||||
|
hasInvokedCallback_1 = true;
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Actually invoke it, passing through any supplied args
|
||||||
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
|
|||||||
@@ -37,19 +37,41 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
await EnsureReady();
|
await EnsureReady();
|
||||||
var virtualConnectionClient = await GetOrCreateVirtualConnectionClientAsync();
|
var virtualConnectionClient = await GetOrCreateVirtualConnectionClientAsync();
|
||||||
|
|
||||||
using (var virtualConnection = _currentVirtualConnectionClient.OpenVirtualConnection())
|
bool shouldDisposeVirtualConnection = true;
|
||||||
|
Stream virtualConnection = null;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
virtualConnection = _currentVirtualConnectionClient.OpenVirtualConnection();
|
||||||
|
|
||||||
// Send request
|
// Send request
|
||||||
await WriteJsonLineAsync(virtualConnection, invocationInfo);
|
await WriteJsonLineAsync(virtualConnection, invocationInfo);
|
||||||
|
|
||||||
// Receive response
|
// Determine what kind of response format is expected
|
||||||
var response = await ReadJsonAsync<RpcResponse<T>>(virtualConnection);
|
if (typeof(T) == typeof(Stream))
|
||||||
if (response.ErrorMessage != null)
|
|
||||||
{
|
{
|
||||||
throw new NodeInvocationException(response.ErrorMessage, response.ErrorDetails);
|
// 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);
|
||||||
|
if (response.ErrorMessage != null)
|
||||||
|
{
|
||||||
|
throw new NodeInvocationException(response.ErrorMessage, response.ErrorDetails);
|
||||||
|
}
|
||||||
|
|
||||||
return response.Result;
|
return response.Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (shouldDisposeVirtualConnection)
|
||||||
|
{
|
||||||
|
virtualConnection.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +202,7 @@ namespace Microsoft.AspNetCore.NodeServices
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable 649 // These properties are populated via JSON deserialization
|
#pragma warning disable 649 // These properties are populated via JSON deserialization
|
||||||
private class RpcResponse<TResult>
|
private class RpcJsonResponse<TResult>
|
||||||
{
|
{
|
||||||
public TResult Result { get; set; }
|
public TResult Result { get; set; }
|
||||||
public string ErrorMessage { get; set; }
|
public string ErrorMessage { get; set; }
|
||||||
|
|||||||
@@ -29,14 +29,32 @@ virtualConnectionServer.createInterface(server).on('connection', (connection: Du
|
|||||||
const invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
const invokedModule = dynamicRequire(path.resolve(process.cwd(), invocation.moduleName));
|
||||||
const invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
const invokedFunction = invocation.exportedFunctionName ? invokedModule[invocation.exportedFunctionName] : invokedModule;
|
||||||
|
|
||||||
// Actually invoke it, passing the callback followed by any supplied args
|
// Prepare a callback for accepting non-streamed JSON responses
|
||||||
|
let hasInvokedCallback = false;
|
||||||
const invocationCallback = (errorValue, successValue) => {
|
const invocationCallback = (errorValue, successValue) => {
|
||||||
|
if (hasInvokedCallback) {
|
||||||
|
throw new Error('Cannot supply more than one result. The callback has already been invoked,'
|
||||||
|
+ ' or the result stream has already been accessed');
|
||||||
|
}
|
||||||
|
|
||||||
|
hasInvokedCallback = true;
|
||||||
connection.end(JSON.stringify({
|
connection.end(JSON.stringify({
|
||||||
result: successValue,
|
result: successValue,
|
||||||
errorMessage: errorValue && (errorValue.message || errorValue),
|
errorMessage: errorValue && (errorValue.message || errorValue),
|
||||||
errorDetails: errorValue && (errorValue.stack || null)
|
errorDetails: errorValue && (errorValue.stack || null)
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Also support streamed binary responses
|
||||||
|
Object.defineProperty(invocationCallback, 'stream', {
|
||||||
|
enumerable: true,
|
||||||
|
get: (): Duplex => {
|
||||||
|
hasInvokedCallback = true;
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Actually invoke it, passing through any supplied args
|
||||||
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
invokedFunction.apply(null, [invocationCallback].concat(invocation.args));
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
connection.end(JSON.stringify({
|
connection.end(JSON.stringify({
|
||||||
|
|||||||
Reference in New Issue
Block a user