using System.Diagnostics; namespace w4c_workflows.Services.Execution; /// /// Runs a language whose program is a single file executed by an interpreter /// (shell → sh, python → python3, javascript → node). Input is written to stdin /// as JSON; output follows the stdout contract. /// public class SubprocessScriptExecutor : IScriptExecutor { private readonly string _language; private readonly string _executable; private readonly TimeSpan _timeout; public SubprocessScriptExecutor(string language, string executable, IConfiguration config) { _language = language; _executable = executable; _timeout = TimeSpan.FromSeconds(ParseInt(config["Workflows:TaskTimeoutSeconds"], 60)); } public string Language => _language; public bool IsAvailable() => ProcessRunner.FindInPath(_executable) != null; public async Task ExecuteAsync(TaskInvocation invocation, CancellationToken ct) { var sw = Stopwatch.StartNew(); try { var workingDir = ExecutionHelpers.ResolveWorkingDir(invocation); var entryPath = Path.Combine(workingDir, invocation.EntryFile); var output = await ProcessRunner.RunAsync( _executable, new[] { entryPath }, workingDir, ExecutionHelpers.BuildEnvironment(invocation), invocation.Input, _timeout, ct); return ExecutionHelpers.ToResult(output, sw.Elapsed); } catch (Exception ex) { sw.Stop(); return new ExecutionResult(false, -1, string.Empty, string.Empty, null, ex.Message, sw.Elapsed); } } private static int ParseInt(string? text, int fallback) => int.TryParse(text, out var value) && value > 0 ? value : fallback; }