From c37d3aecb62995f94b78ff010f7623adb2b28e13 Mon Sep 17 00:00:00 2001 From: Justin SB Date: Thu, 5 Jan 2023 11:17:14 -0500 Subject: [PATCH] refactor pod warmup to avoid vet warning By refactoring the parallel operation into a separate function, it should be easier to read and we avoid a loop-closure go-tcha. --- porch/func/internal/podevaluator.go | 51 +++++++++++++++++++---------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/porch/func/internal/podevaluator.go b/porch/func/internal/podevaluator.go index 37ab997525..d8a06e2f44 100644 --- a/porch/func/internal/podevaluator.go +++ b/porch/func/internal/podevaluator.go @@ -205,29 +205,44 @@ func (pcm *podCacheManager) warmupCache(podTTLConfig string) error { return err } - // We create the pods concurrently to speed it up. + // We precreate the pods (concurrently) to speed it up. + forEachConcurrently(podsTTL, func(fnImage string, ttlStr string) { + klog.Infof("preloading pod cache for function %v with TTL %v", fnImage, ttlStr) + + ttl, err := time.ParseDuration(ttlStr) + if err != nil { + klog.Warningf("unable to parse duration from the config file for function %v: %w", fnImage, err) + ttl = pcm.podTTL + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + // We invoke the function with useGenerateName=false so that the pod name is fixed, + // since we want to ensure only one pod is created for each function. + pcm.podManager.getFuncEvalPodClient(ctx, fnImage, ttl, false) + klog.Infof("preloaded pod cache for function %v", fnImage) + }) + + return nil +} + +// forEachConcurrently runs fn for each entry in the map m, in parallel goroutines. +// It waits for each to finish before returning. +func forEachConcurrently(m map[string]string, fn func(k string, v string)) { var wg sync.WaitGroup - for fnImage, ttlStr := range podsTTL { + for k, v := range m { + k := k + v := v + wg.Add(1) - go func(img, ttlSt string) { - klog.Infof("preloading pod cache for function %v with TTL %v", img, ttlSt) + go func() { defer wg.Done() - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) - defer cancel() - ttl, err := time.ParseDuration(ttlSt) - if err != nil { - klog.Warningf("unable to parse duration from the config file for function %v: %w", fnImage, err) - ttl = pcm.podTTL - } - // We invoke the function with useGenerateName=false so that the pod name is fixed, - // since we want to ensure only one pod is created for each function. - pcm.podManager.getFuncEvalPodClient(ctx, img, ttl, false) - klog.Infof("preloaded pod cache for function %v", img) - }(fnImage, ttlStr) + fn(k, v) + }() } - // Wait for the cache warming up to finish before returning. + // Wait for all the functions to complete. wg.Wait() - return nil } // podCacheManager responds to the requestCh and the podReadyCh and does the