@@ -7,13 +7,16 @@ import (
77 "bufio"
88 "bytes"
99 "container/ring"
10+ "context"
1011 "encoding/base32"
1112 "encoding/json"
1213 "fmt"
1314 "io"
1415 "os/exec"
1516 "strconv"
1617 "strings"
18+ "sync"
19+ "time"
1720
1821 "github.com/openrundev/openrun/internal/types"
1922)
@@ -45,6 +48,32 @@ func genLowerCaseId(name string) string {
4548 return strings .ToLower (base32encoder .EncodeToString ([]byte (name )))
4649}
4750
51+ var mu sync.Mutex
52+ var buildLockChannel chan string // channel to hold the build ids, max size is MaxConcurrentBuilds
53+
54+ // acquireBuildLock acquires a build lock for the given build id. If the lock is not available,
55+ // it will wait for the lock to be available or the context to be done.
56+ // The lock is released when the returned function is called.
57+ func acquireBuildLock (ctx context.Context , config * types.SystemConfig , buildId string ) (func (), error ) {
58+ mu .Lock ()
59+ if buildLockChannel == nil {
60+ buildLockChannel = make (chan string , config .MaxConcurrentBuilds )
61+ }
62+ mu .Unlock ()
63+
64+ timer := time .NewTimer (time .Duration (config .MaxBuildWaitSecs ) * time .Second )
65+ defer timer .Stop ()
66+
67+ select {
68+ case buildLockChannel <- buildId :
69+ return func () { <- buildLockChannel }, nil
70+ case <- ctx .Done ():
71+ return nil , ctx .Err ()
72+ case <- timer .C :
73+ return nil , context .DeadlineExceeded
74+ }
75+ }
76+
4877func GenContainerName (appId types.AppId , contentHash string ) ContainerName {
4978 if contentHash == "" {
5079 return ContainerName (fmt .Sprintf ("clc-%s" , appId ))
@@ -76,6 +105,12 @@ func (c ContainerCommand) RemoveImage(config *types.SystemConfig, name ImageName
76105}
77106
78107func (c ContainerCommand ) BuildImage (config * types.SystemConfig , name ImageName , sourceUrl , containerFile string , containerArgs map [string ]string ) error {
108+ releaseLock , err := acquireBuildLock (context .Background (), config , string (name ))
109+ if err != nil {
110+ return fmt .Errorf ("error acquiring build lock: %w" , err )
111+ }
112+ defer releaseLock ()
113+
79114 c .Debug ().Msgf ("Building image %s from %s with %s" , name , containerFile , sourceUrl )
80115 args := []string {config .ContainerCommand , "build" , "-t" , string (name ), "-f" , containerFile }
81116
0 commit comments