Skip to content

Commit dd2c375

Browse files
committed
feat(Runner): Implemented the ScriptProcessExecutor (WIP)
Signed-off-by: Charles d'Avernas <charles.davernas@neuroglia.io>
1 parent 4b2b316 commit dd2c375

File tree

5 files changed

+40
-3
lines changed

5 files changed

+40
-3
lines changed

src/runner/Synapse.Runner/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ FROM mcr.microsoft.com/dotnet/runtime:8.0 AS base
22
USER root
33
RUN apt-get update
44
RUN apt-get install -y jq
5+
RUN apt-get install -y nodejs
6+
RUN apt-get install -y python3
57
USER app
68
WORKDIR /app
79

src/runner/Synapse.Runner/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
services.AddYamlDotNetSerializer();
4040
services.AddJQExpressionEvaluator();
4141
services.AddJavaScriptExpressionEvaluator();
42+
services.AddNodeJSScriptExecutor();
43+
services.AddPythonScriptExecutor();
4244
services.AddSynapseHttpApiClient(http =>
4345
{
4446
http.BaseAddress = options.Api.BaseAddress;

src/runner/Synapse.Runner/Services/Executors/ScriptProcessExecutor.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,48 @@ namespace Synapse.Runner.Services.Executors;
2222
/// <param name="executorFactory">The service used to create <see cref="ITaskExecutor"/>s</param>
2323
/// <param name="context">The current <see cref="ITaskExecutionContext"/></param>
2424
/// <param name="serializer">The service used to serialize/deserialize objects to/from JSON</param>
25-
public class ScriptProcessExecutor(IServiceProvider serviceProvider, ILogger<ScriptProcessExecutor> logger, ITaskExecutionContextFactory executionContextFactory, ITaskExecutorFactory executorFactory, ITaskExecutionContext<RunTaskDefinition> context, IJsonSerializer serializer)
25+
/// <param name="externalResourceProvider">The service used to resolve external resources</param>
26+
/// <param name="scriptExecutorProvider">The service used to provide <see cref="IScriptExecutor"/>s</param>
27+
public class ScriptProcessExecutor(IServiceProvider serviceProvider, ILogger<ScriptProcessExecutor> logger, ITaskExecutionContextFactory executionContextFactory, ITaskExecutorFactory executorFactory,
28+
ITaskExecutionContext<RunTaskDefinition> context, IJsonSerializer serializer, IExternalResourceProvider externalResourceProvider, IScriptExecutorProvider scriptExecutorProvider)
2629
: TaskExecutor<RunTaskDefinition>(serviceProvider, logger, executionContextFactory, executorFactory, context, serializer)
2730
{
2831

32+
/// <summary>
33+
/// Gets the service used to resolve external resources
34+
/// </summary>
35+
protected IExternalResourceProvider ExternalResourceProvider { get; } = externalResourceProvider;
36+
37+
/// <summary>
38+
/// Gets the service used to provide <see cref="IScriptExecutor"/>s
39+
/// </summary>
40+
protected IScriptExecutorProvider ScriptExecutorProvider { get; } = scriptExecutorProvider;
41+
2942
/// <summary>
3043
/// Gets the definition of the script process to run
3144
/// </summary>
3245
protected ScriptProcessDefinition ProcessDefinition => this.Task.Definition.Run.Script!;
3346

3447
/// <inheritdoc/>
35-
protected override Task DoExecuteAsync(CancellationToken cancellationToken)
48+
protected override async Task DoExecuteAsync(CancellationToken cancellationToken)
3649
{
37-
return System.Threading.Tasks.Task.CompletedTask; //todo: implement
50+
var executor = this.ScriptExecutorProvider.GetExecutor(this.ProcessDefinition.Language) ?? throw new NullReferenceException($"Failed to find a script executor for the specified language '{this.ProcessDefinition.Language}'");
51+
var script = this.ProcessDefinition.Code;
52+
if (string.IsNullOrWhiteSpace(script))
53+
{
54+
if (this.ProcessDefinition.Source == null) throw new NullReferenceException("The script's code or resource must be set");
55+
using var stream = await this.ExternalResourceProvider.ReadAsync(this.Task.Workflow.Definition, this.ProcessDefinition.Source, cancellationToken).ConfigureAwait(false);
56+
using var streamReader = new StreamReader(stream);
57+
script = await streamReader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
58+
}
59+
using var process = await executor.ExecuteAsync(script, null, this.ProcessDefinition.Environment, cancellationToken).ConfigureAwait(false);
60+
await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false);
61+
var stdOut = await process.StandardOutput.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
62+
var stdErr = await process.StandardError.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
63+
//todo: urgent: fix the script process so that we provide:
64+
//1. (evaluated) arguments
65+
//2. (evaluated) environment variables
66+
//3. a way to decide, like for shell, where to read the output from: stdOut, file? or (exit) code
3867
}
3968

4069
}

src/runner/Synapse.Runner/Synapse.Runner.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
<PackageReference Include="Neuroglia.Data.Expressions.JavaScript" Version="4.10.0" />
4444
<PackageReference Include="Neuroglia.Data.Expressions.JQ" Version="4.10.0" />
4545
<PackageReference Include="Neuroglia.Eventing.CloudEvents.Infrastructure" Version="4.10.0" />
46+
<PackageReference Include="Neuroglia.Scripting.NodeJS" Version="4.11.0" />
47+
<PackageReference Include="Neuroglia.Scripting.Python" Version="4.11.0" />
4648
<PackageReference Include="protobuf-net.Grpc.ClientFactory" Version="1.1.1" />
4749
<PackageReference Include="System.Reactive" Version="6.0.1" />
4850
</ItemGroup>

src/runner/Synapse.Runner/Usings.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
global using Microsoft.Extensions.Logging;
1818
global using Neuroglia.Data.Expressions.JavaScript;
1919
global using Neuroglia.Data.Expressions.JQ;
20+
global using Neuroglia.Scripting;
21+
global using Neuroglia.Scripting.Services;
2022
global using Neuroglia.Serialization;
2123
global using ServerlessWorkflow.Sdk;
2224
global using ServerlessWorkflow.Sdk.Models;

0 commit comments

Comments
 (0)