Files
seaweedfs/weed/util/error_wait_group_test.go
Chris LuandGitHub 944d967502 refactor: extract EC orchestration into a shared weed/ec package (#10760)
* shell: move ErrorWaitGroup to weed/util

* shell: remove unused CandidateEcNode and EcRack types

* ec: extract EC orchestration logic from weed/shell into weed/ec

Move the EC node/topology model, balance engine, encode pipeline, decode
pipeline, and rebuild engine into a new weed/ec package so shell commands
and maintenance workers can share the logic. Shell commands keep flag
parsing and delegate through a small ec.Env (dial option, topology fetch,
volume locations, lock check). Tests move along with the code.

* shell: remove unused proportional-rebalance type stubs

* ec: move scrub, replication check, and shard unmount engines into weed/ec

* worker: share the EC generation-aware shard counter from weed/ec

* ec: gofmt

* shell: drop EC aliases with no remaining callers

* ec: guard a missing topology hook and nil disk entries in topology helpers

* ec: drop trailing newlines from decode error strings

* ec: re-check the shell lock before applying shard unmounts

* shell: trim -node entries in ec.scrub
2026-08-14 13:54:12 -07:00

95 lines
1.9 KiB
Go

package util
import (
"errors"
"testing"
"time"
)
func TestExecuteParallelTaskGroups(t *testing.T) {
firstTaskStarted := make(chan struct{})
firstTaskRelease := make(chan struct{})
secondTaskStarted := make(chan struct{})
secondTaskInFirstGroupStarted := make(chan struct{})
done := make(chan error, 1)
go func() {
done <- ExecuteParallelTaskGroups(2, [][]ErrorWaitGroupTask{
{
func() error {
close(firstTaskStarted)
<-firstTaskRelease
return nil
},
func() error {
close(secondTaskInFirstGroupStarted)
return nil
},
},
{
func() error {
close(secondTaskStarted)
return nil
},
},
})
}()
select {
case <-firstTaskStarted:
case <-time.After(time.Second):
t.Fatal("first task did not start")
}
select {
case <-secondTaskStarted:
case <-time.After(time.Second):
t.Fatal("independent task group did not start in parallel")
}
select {
case <-secondTaskInFirstGroupStarted:
t.Fatal("tasks in the same group ran in parallel")
default:
}
close(firstTaskRelease)
select {
case err := <-done:
if err != nil {
t.Fatalf("execute parallel task groups: %v", err)
}
case <-time.After(time.Second):
t.Fatal("parallel task groups did not finish")
}
}
func TestExecuteParallelTaskGroupsStopsOnlyFailedGroup(t *testing.T) {
expectedErr := errors.New("move failed")
failedGroupContinued := false
otherGroupRan := false
err := ExecuteParallelTaskGroups(1, [][]ErrorWaitGroupTask{
{
func() error { return expectedErr },
func() error {
failedGroupContinued = true
return nil
},
},
{
func() error {
otherGroupRan = true
return nil
},
},
})
if !errors.Is(err, expectedErr) {
t.Fatalf("expected task error, got %v", err)
}
if failedGroupContinued {
t.Fatal("task after a failed task in the same group ran")
}
if !otherGroupRan {
t.Fatal("independent task group did not run")
}
}