From 2bfa6335a20eddb5807d0e65544b3ae2c03cc78b Mon Sep 17 00:00:00 2001 From: Wes Date: Thu, 7 Mar 2024 16:28:31 -0700 Subject: [PATCH] fix: parallelize deployments (#1042) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #1031 Introduces non-blocking deploys so that they can while other modules are build. BEFORE (20s cold, 11s warm): ![Screenshot 2024-03-07 at 1 28 09 PM](https://github.com/TBD54566975/ftl/assets/51647/f03b0cfe-8c77-4aba-aee7-689561391618) AFTER (16s cold, 8s warm): ![Screenshot 2024-03-07 at 1 29 23 PM](https://github.com/TBD54566975/ftl/assets/51647/8148625e-7b5d-4082-84fe-4a7fffca60e4) --- buildengine/engine.go | 48 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/buildengine/engine.go b/buildengine/engine.go index 45607fe569..2ce8530916 100644 --- a/buildengine/engine.go +++ b/buildengine/engine.go @@ -166,9 +166,7 @@ func (e *Engine) Dev(ctx context.Context, period time.Duration) error { logger := log.FromContext(ctx) // Build and deploy all modules first. - err := e.buildWithCallback(ctx, func(ctx context.Context, module Module) error { - return Deploy(ctx, module, 1, true, e.client) - }) + err := e.buildAndDeploy(ctx, 1, true) if err != nil { logger.Errorf(err, "initial deploy failed") } @@ -223,13 +221,45 @@ func (e *Engine) Dev(ctx context.Context, period time.Duration) error { } func (e *Engine) buildAndDeploy(ctx context.Context, replicas int32, waitForDeployOnline bool, modules ...string) error { - err := e.buildWithCallback(ctx, func(ctx context.Context, module Module) error { - return Deploy(ctx, module, replicas, waitForDeployOnline, e.client) - }, modules...) - if err != nil { - return err + if len(modules) == 0 { + modules = maps.Keys(e.modules) } - return nil + + deployQueue := make(chan Module, len(modules)) + wg, ctx := errgroup.WithContext(ctx) + + wg.Go(func() error { + defer close(deployQueue) + + return e.buildWithCallback(ctx, func(ctx context.Context, module Module) error { + select { + case deployQueue <- module: + return nil + case <-ctx.Done(): + return ctx.Err() + } + }, modules...) + }) + + for i := 0; i < len(modules); i++ { + wg.Go(func() error { + for { + select { + case module, ok := <-deployQueue: + if !ok { + return nil + } + if err := Deploy(ctx, module, replicas, waitForDeployOnline, e.client); err != nil { + return err + } + case <-ctx.Done(): + return ctx.Err() + } + } + }) + } + + return wg.Wait() } type buildCallback func(ctx context.Context, module Module) error