feat(process): preserve wait task snapshots on failure

This commit is contained in:
Virgil 2026-04-04 07:08:54 +00:00
parent e1f5b0ff40
commit 3ac213a058
3 changed files with 55 additions and 1 deletions

View file

@ -91,6 +91,8 @@ type TaskProcessGet struct {
}
// TaskProcessWait waits for a managed process to finish through Core.PERFORM.
// Successful exits return an Info snapshot. Unsuccessful exits return a
// TaskProcessWaitError value that preserves the final snapshot.
//
// Example:
//
@ -100,6 +102,30 @@ type TaskProcessWait struct {
ID string
}
// TaskProcessWaitError is returned as the task value when TaskProcessWait
// completes with a non-successful process outcome. It preserves the final
// process snapshot while still behaving like the underlying wait error.
type TaskProcessWaitError struct {
Info Info
Err error
}
// Error implements error.
func (e *TaskProcessWaitError) Error() string {
if e == nil || e.Err == nil {
return ""
}
return e.Err.Error()
}
// Unwrap returns the underlying wait error.
func (e *TaskProcessWaitError) Unwrap() error {
if e == nil {
return nil
}
return e.Err
}
// TaskProcessOutput requests the captured output of a managed process through Core.PERFORM.
//
// Example:

View file

@ -727,7 +727,13 @@ func (s *Service) handleTask(c *core.Core, task core.Task) core.Result {
info, err := s.Wait(m.ID)
if err != nil {
return core.Result{Value: err, OK: false}
return core.Result{
Value: &TaskProcessWaitError{
Info: info,
Err: err,
},
OK: true,
}
}
return core.Result{Value: info, OK: true}

View file

@ -946,6 +946,28 @@ func TestService_OnStartup(t *testing.T) {
assert.Equal(t, 0, info.ExitCode)
})
t.Run("preserves final snapshot when process.wait task fails", func(t *testing.T) {
svc, c := newTestService(t)
err := svc.OnStartup(context.Background())
require.NoError(t, err)
proc, err := svc.Start(context.Background(), "sh", "-c", "exit 7")
require.NoError(t, err)
result := c.PERFORM(TaskProcessWait{ID: proc.ID})
require.True(t, result.OK)
errValue, ok := result.Value.(error)
require.True(t, ok)
var waitErr *TaskProcessWaitError
require.ErrorAs(t, errValue, &waitErr)
assert.Contains(t, waitErr.Error(), "process exited with code 7")
assert.Equal(t, proc.ID, waitErr.Info.ID)
assert.Equal(t, StatusExited, waitErr.Info.Status)
assert.Equal(t, 7, waitErr.Info.ExitCode)
})
t.Run("registers process.list task", func(t *testing.T) {
svc, c := newTestService(t)