package workflow import ( "context" "encoding/json" "errors" "sync" ) var ErrExecutorNotFound = errors.New("workflow executor not found") type Executor interface { Execute(context.Context, json.RawMessage) (json.RawMessage, error) } type ExecutorFunc func(context.Context, json.RawMessage) (json.RawMessage, error) func (function ExecutorFunc) Execute(ctx context.Context, input json.RawMessage) (json.RawMessage, error) { return function(ctx, input) } type Registry struct { mu sync.RWMutex executors map[string]Executor } func NewRegistry() *Registry { registry := &Registry{executors: make(map[string]Executor)} registry.Register("noop", ExecutorFunc(func(_ context.Context, input json.RawMessage) (json.RawMessage, error) { if len(input) == 0 { return json.RawMessage(`{}`), nil } return input, nil })) return registry } func (registry *Registry) Register(operation string, executor Executor) { registry.mu.Lock() defer registry.mu.Unlock() registry.executors[operation] = executor } func (registry *Registry) Execute( ctx context.Context, operation string, input json.RawMessage, ) (json.RawMessage, error) { registry.mu.RLock() executor, exists := registry.executors[operation] registry.mu.RUnlock() if !exists { return nil, ErrExecutorNotFound } return executor.Execute(ctx, input) }