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  }