diff options
Diffstat (limited to 'internal/executor/executor.go')
| -rw-r--r-- | internal/executor/executor.go | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/internal/executor/executor.go b/internal/executor/executor.go index 51f468e..eb23c02 100644 --- a/internal/executor/executor.go +++ b/internal/executor/executor.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log/slog" + "path/filepath" "sync" "time" @@ -12,6 +13,13 @@ import ( "github.com/google/uuid" ) +// LogPather is an optional interface runners can implement to provide the log +// directory for an execution before it starts. The pool uses this to persist +// log paths at CreateExecution time rather than waiting until execution ends. +type LogPather interface { + ExecLogDir(execID string) string +} + // Runner executes a single task and returns the result. type Runner interface { Run(ctx context.Context, t *task.Task, exec *storage.Execution) error @@ -115,6 +123,16 @@ func (p *Pool) execute(ctx context.Context, t *task.Task) { Status: "RUNNING", } + // Pre-populate log paths so they're available in the DB immediately — + // before the subprocess starts — enabling live tailing and debugging. + if lp, ok := p.runner.(LogPather); ok { + if logDir := lp.ExecLogDir(execID); logDir != "" { + exec.StdoutPath = filepath.Join(logDir, "stdout.log") + exec.StderrPath = filepath.Join(logDir, "stderr.log") + exec.ArtifactDir = logDir + } + } + // Record execution start. if err := p.store.CreateExecution(exec); err != nil { p.logger.Error("failed to create execution record", "error", err) |
