From 0546b42ce3dabf286437e69221a9ee5bfd754931 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 23:17:11 +0000 Subject: [PATCH] feat(process): add Core task for run execution --- actions.go | 9 +++++++++ service.go | 33 +++++++++++++++++++++++++++++---- service_test.go | 15 ++++++++++++--- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/actions.go b/actions.go index 7f33cf8..a09e520 100644 --- a/actions.go +++ b/actions.go @@ -4,6 +4,15 @@ import "time" // --- ACTION messages (broadcast via Core.ACTION) --- +// TaskProcessRun requests synchronous command execution through Core.PERFORM. +// The handler returns the combined command output on success. +type TaskProcessRun struct { + Command string + Args []string + Dir string + Env []string +} + // ActionProcessStarted is broadcast when a process begins execution. type ActionProcessStarted struct { ID string diff --git a/service.go b/service.go index 5fd1339..bc5b52c 100644 --- a/service.go +++ b/service.go @@ -30,10 +30,11 @@ var ( type Service struct { *core.ServiceRuntime[Options] - processes map[string]*Process - mu sync.RWMutex - bufSize int - idCounter atomic.Uint64 + processes map[string]*Process + mu sync.RWMutex + bufSize int + idCounter atomic.Uint64 + registrations sync.Once } // Options configures the process service. @@ -64,6 +65,11 @@ func NewService(opts Options) func(*core.Core) (any, error) { // OnStartup implements core.Startable. func (s *Service) OnStartup(ctx context.Context) error { + s.registrations.Do(func() { + if s.Core() != nil { + s.Core().RegisterTask(s.handleTask) + } + }) return nil } @@ -402,3 +408,22 @@ func (s *Service) RunWithOptions(ctx context.Context, opts RunOptions) (string, } return output, nil } + +// handleTask dispatches Core.PERFORM messages for the process service. +func (s *Service) handleTask(c *core.Core, task core.Task) core.Result { + switch m := task.(type) { + case TaskProcessRun: + output, err := s.RunWithOptions(c.Context(), RunOptions{ + Command: m.Command, + Args: m.Args, + Dir: m.Dir, + Env: m.Env, + }) + if err != nil { + return core.Result{Value: err, OK: false} + } + return core.Result{Value: output, OK: true} + default: + return core.Result{} + } +} diff --git a/service_test.go b/service_test.go index 868b7a3..db43004 100644 --- a/service_test.go +++ b/service_test.go @@ -391,10 +391,19 @@ func TestService_OnShutdown(t *testing.T) { } func TestService_OnStartup(t *testing.T) { - t.Run("returns nil", func(t *testing.T) { - svc, _ := newTestService(t) + t.Run("registers process.run task", func(t *testing.T) { + svc, c := newTestService(t) + err := svc.OnStartup(context.Background()) - assert.NoError(t, err) + require.NoError(t, err) + + result := c.PERFORM(TaskProcessRun{ + Command: "echo", + Args: []string{"action-run"}, + }) + + require.True(t, result.OK) + assert.Contains(t, result.Value.(string), "action-run") }) }