node build fixed
This commit is contained in:
96
seanime-2.9.10/internal/util/parallel/parallel.go
Normal file
96
seanime-2.9.10/internal/util/parallel/parallel.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package parallel
|
||||
|
||||
import (
|
||||
"github.com/samber/lo"
|
||||
"seanime/internal/util/limiter"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// EachTask iterates over elements of collection and invokes the task function for each element.
|
||||
// `task` is called in parallel.
|
||||
func EachTask[T any](collection []T, task func(item T, index int)) {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for i, item := range collection {
|
||||
wg.Add(1)
|
||||
go func(_item T, _i int) {
|
||||
defer wg.Done()
|
||||
task(_item, _i)
|
||||
}(item, i)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// EachTaskL is the same as EachTask, but takes a pointer to limiter.Limiter.
|
||||
func EachTaskL[T any](collection []T, rl *limiter.Limiter, task func(item T, index int)) {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for i, item := range collection {
|
||||
wg.Add(1)
|
||||
go func(_item T, _i int) {
|
||||
defer wg.Done()
|
||||
rl.Wait()
|
||||
task(_item, _i)
|
||||
}(item, i)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
type SettledResults[T comparable, R any] struct {
|
||||
Collection []T
|
||||
Fulfilled map[T]R
|
||||
Results []R
|
||||
Rejected map[T]error
|
||||
}
|
||||
|
||||
// NewSettledResults returns a pointer to a new SettledResults struct.
|
||||
func NewSettledResults[T comparable, R any](c []T) *SettledResults[T, R] {
|
||||
return &SettledResults[T, R]{
|
||||
Collection: c,
|
||||
Fulfilled: map[T]R{},
|
||||
Rejected: map[T]error{},
|
||||
}
|
||||
}
|
||||
|
||||
// GetFulfilledResults returns a pointer to the slice of fulfilled results and a boolean indicating whether the slice is not nil.
|
||||
func (sr *SettledResults[T, R]) GetFulfilledResults() (*[]R, bool) {
|
||||
if sr.Results != nil {
|
||||
return &sr.Results, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// AllSettled executes the provided task function once, in parallel for each element in the slice passed to NewSettledResults.
|
||||
// It returns a map of fulfilled results and a map of errors whose keys are the elements of the slice.
|
||||
func (sr *SettledResults[T, R]) AllSettled(task func(item T, index int) (R, error)) (map[T]R, map[T]error) {
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
|
||||
for i, item := range sr.Collection {
|
||||
wg.Add(1)
|
||||
go func(_item T, _i int) {
|
||||
|
||||
res, err := task(_item, _i)
|
||||
|
||||
mu.Lock()
|
||||
if err != nil {
|
||||
sr.Rejected[_item] = err
|
||||
} else {
|
||||
sr.Fulfilled[_item] = res
|
||||
}
|
||||
mu.Unlock()
|
||||
wg.Done()
|
||||
|
||||
}(item, i)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
sr.Results = lo.MapToSlice(sr.Fulfilled, func(key T, value R) R {
|
||||
return value
|
||||
})
|
||||
|
||||
return sr.Fulfilled, sr.Rejected
|
||||
}
|
||||
78
seanime-2.9.10/internal/util/parallel/parallel_test.go
Normal file
78
seanime-2.9.10/internal/util/parallel/parallel_test.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package parallel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/sourcegraph/conc/pool"
|
||||
"github.com/sourcegraph/conc/stream"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func fakeAPICall(id int) (int, error) {
|
||||
//time.Sleep(time.Millisecond * time.Duration(100+rand.Intn(500)))
|
||||
time.Sleep(time.Millisecond * 200)
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func TestAllSettled(t *testing.T) {
|
||||
|
||||
ids := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
|
||||
|
||||
sr := NewSettledResults[int, int](ids)
|
||||
sr.AllSettled(func(item int, index int) (int, error) {
|
||||
return fakeAPICall(item)
|
||||
})
|
||||
|
||||
fulfilled, ok := sr.GetFulfilledResults()
|
||||
|
||||
if !ok {
|
||||
t.Error("expected results, got error")
|
||||
}
|
||||
|
||||
for _, v := range *fulfilled {
|
||||
t.Log(v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestConc(t *testing.T) {
|
||||
|
||||
ids := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
|
||||
|
||||
fetch := func(ids []int) ([]int, error) {
|
||||
p := pool.NewWithResults[int]().WithErrors()
|
||||
for _, id := range ids {
|
||||
id := id
|
||||
p.Go(func() (int, error) {
|
||||
return fakeAPICall(id)
|
||||
})
|
||||
}
|
||||
return p.Wait()
|
||||
}
|
||||
|
||||
res, _ := fetch(ids)
|
||||
|
||||
for _, v := range res {
|
||||
t.Log(v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestConcStream(t *testing.T) {
|
||||
|
||||
ids := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
|
||||
|
||||
strm := stream.New()
|
||||
for _, id := range ids {
|
||||
id := id
|
||||
strm.Go(func() stream.Callback {
|
||||
res, err := fakeAPICall(id)
|
||||
// This will print in the order the tasks were submitted
|
||||
return func() {
|
||||
fmt.Println(res, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
strm.Wait()
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user