fix(process): reject duplicate runner spec names
This commit is contained in:
parent
fa79e4eee7
commit
f98bbad5ac
2 changed files with 56 additions and 0 deletions
26
runner.go
26
runner.go
|
|
@ -16,6 +16,9 @@ type Runner struct {
|
|||
// ErrRunnerNoService is returned when a runner was created without a service.
|
||||
var ErrRunnerNoService = coreerr.E("", "runner service is nil", nil)
|
||||
|
||||
// ErrRunnerInvalidSpecName is returned when a RunSpec name is empty or duplicated.
|
||||
var ErrRunnerInvalidSpecName = coreerr.E("", "runner spec names must be non-empty and unique", nil)
|
||||
|
||||
// NewRunner creates a runner for the given service.
|
||||
func NewRunner(svc *Service) *Runner {
|
||||
return &Runner{service: svc}
|
||||
|
|
@ -74,6 +77,9 @@ func (r *Runner) RunAll(ctx context.Context, specs []RunSpec) (*RunAllResult, er
|
|||
if err := r.ensureService(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateSpecs(specs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
start := time.Now()
|
||||
|
||||
// Build dependency graph
|
||||
|
|
@ -239,6 +245,9 @@ func (r *Runner) RunSequential(ctx context.Context, specs []RunSpec) (*RunAllRes
|
|||
if err := r.ensureService(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateSpecs(specs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
start := time.Now()
|
||||
results := make([]RunResult, 0, len(specs))
|
||||
|
||||
|
|
@ -282,6 +291,9 @@ func (r *Runner) RunParallel(ctx context.Context, specs []RunSpec) (*RunAllResul
|
|||
if err := r.ensureService(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validateSpecs(specs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
start := time.Now()
|
||||
results := make([]RunResult, len(specs))
|
||||
|
||||
|
|
@ -312,3 +324,17 @@ func (r *Runner) RunParallel(ctx context.Context, specs []RunSpec) (*RunAllResul
|
|||
|
||||
return aggResult, nil
|
||||
}
|
||||
|
||||
func validateSpecs(specs []RunSpec) error {
|
||||
seen := make(map[string]struct{}, len(specs))
|
||||
for _, spec := range specs {
|
||||
if spec.Name == "" {
|
||||
return coreerr.E("Runner.validateSpecs", "runner spec name is required", ErrRunnerInvalidSpecName)
|
||||
}
|
||||
if _, ok := seen[spec.Name]; ok {
|
||||
return coreerr.E("Runner.validateSpecs", "runner spec name is duplicated", ErrRunnerInvalidSpecName)
|
||||
}
|
||||
seen[spec.Name] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,3 +243,33 @@ func TestRunner_NilService(t *testing.T) {
|
|||
require.Error(t, err)
|
||||
assert.ErrorIs(t, err, ErrRunnerNoService)
|
||||
}
|
||||
|
||||
func TestRunner_InvalidSpecNames(t *testing.T) {
|
||||
runner := newTestRunner(t)
|
||||
|
||||
t.Run("rejects empty names", func(t *testing.T) {
|
||||
_, err := runner.RunSequential(context.Background(), []RunSpec{
|
||||
{Name: "", Command: "echo", Args: []string{"a"}},
|
||||
})
|
||||
require.Error(t, err)
|
||||
assert.ErrorIs(t, err, ErrRunnerInvalidSpecName)
|
||||
})
|
||||
|
||||
t.Run("rejects duplicate names", func(t *testing.T) {
|
||||
_, err := runner.RunAll(context.Background(), []RunSpec{
|
||||
{Name: "same", Command: "echo", Args: []string{"a"}},
|
||||
{Name: "same", Command: "echo", Args: []string{"b"}},
|
||||
})
|
||||
require.Error(t, err)
|
||||
assert.ErrorIs(t, err, ErrRunnerInvalidSpecName)
|
||||
})
|
||||
|
||||
t.Run("rejects duplicate names in parallel mode", func(t *testing.T) {
|
||||
_, err := runner.RunParallel(context.Background(), []RunSpec{
|
||||
{Name: "one", Command: "echo", Args: []string{"a"}},
|
||||
{Name: "one", Command: "echo", Args: []string{"b"}},
|
||||
})
|
||||
require.Error(t, err)
|
||||
assert.ErrorIs(t, err, ErrRunnerInvalidSpecName)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue