diff --git a/cmd/server/api_get_params_test.go b/cmd/server/api_get_params_test.go index e15734f..383da2c 100644 --- a/cmd/server/api_get_params_test.go +++ b/cmd/server/api_get_params_test.go @@ -69,7 +69,7 @@ func TestGetParamsE2E(t *testing.T) { CacheRoot: cacheDir, LoadJoyContext: generator.RepoLoader(repo), Logger: logger, - ChartPuller: generator.ChartPuller{Logger: logger}, + ChartPuller: generator.MakeChartPuller(logger), }, }) diff --git a/cmd/server/main.go b/cmd/server/main.go index 2a81320..a81645c 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -71,7 +71,7 @@ func run() error { CacheRoot: cfg.CacheRoot, LoadJoyContext: generator.RepoLoader(repo), Logger: logger, - ChartPuller: generator.ChartPuller{Logger: logger}, + ChartPuller: generator.MakeChartPuller(logger), }, }), ReadHeaderTimeout: 5 * time.Second, diff --git a/internal/generator/generator.go b/internal/generator/generator.go index d5b34f7..46ed83e 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "sync" "github.com/rs/zerolog" "gopkg.in/yaml.v3" @@ -23,8 +24,23 @@ type Generator struct { ChartPuller helm.Puller } +type MutexMap sync.Map + +func (m *MutexMap) Get(key string) *sync.Mutex { + value, _ := (*sync.Map)(m).LoadOrStore(key, new(sync.Mutex)) + return value.(*sync.Mutex) +} + type ChartPuller struct { - Logger zerolog.Logger + Logger zerolog.Logger + Mutexes *MutexMap +} + +func MakeChartPuller(logger zerolog.Logger) ChartPuller { + return ChartPuller{ + Logger: logger, + Mutexes: &MutexMap{}, + } } func (puller ChartPuller) Pull(ctx context.Context, opts helm.PullOptions) error { @@ -37,11 +53,16 @@ func (puller ChartPuller) Pull(ctx context.Context, opts helm.PullOptions) error }, } + url, _ := opts.Chart.ToURL() + mutex := puller.Mutexes.Get(url.String()) + + mutex.Lock() + defer mutex.Unlock() + if err := cli.Pull(ctx, opts); err != nil { return fmt.Errorf("%w: %q", err, &buffer) } - url, _ := opts.Chart.ToURL() puller.Logger.Info().Str("chart", url.String()).Msg("successfully pulled chart") return nil