github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/concurrency/adapter.go (about) 1 package concurrency 2 3 import ( 4 "sync" 5 6 "github.com/khulnasoft-lab/defsec/pkg/progress" 7 "github.com/khulnasoft-lab/defsec/pkg/state" 8 ) 9 10 type Context interface { 11 Debug(format string, args ...interface{}) 12 ConcurrencyStrategy() Strategy 13 Tracker() progress.ServiceTracker 14 } 15 16 func Adapt[T any, S any](items []T, ctx Context, adapt func(T) (*S, error)) []S { 17 return AdaptWithState(items, nil, ctx, func(item T, _ *state.State) (*S, error) { 18 return adapt(item) 19 }) 20 } 21 22 func AdaptWithState[T any, S any](items []T, currentState *state.State, ctx Context, adapt func(T, *state.State) (*S, error)) []S { 23 processes := getProcessCount(ctx.ConcurrencyStrategy()) 24 ctx.Debug("Using %d processes to adapt %d resources", processes, len(items)) 25 26 mu := sync.Mutex{} 27 28 var ch = make(chan T, 50) 29 wg := sync.WaitGroup{} 30 wg.Add(processes) 31 32 var results []S 33 34 for i := 0; i < processes; i++ { 35 go func() { 36 for { 37 in, ok := <-ch 38 if !ok { 39 wg.Done() 40 return 41 } 42 out, err := adapt(in, currentState) 43 ctx.Tracker().IncrementResource() 44 if err != nil { 45 ctx.Debug("Error while adapting resource %v: %w", in, err) 46 continue 47 } 48 49 if out != nil { 50 mu.Lock() 51 results = append(results, *out) 52 mu.Unlock() 53 } 54 } 55 }() 56 } 57 58 for _, item := range items { 59 ch <- item 60 } 61 62 close(ch) 63 wg.Wait() 64 65 return results 66 }