Skip to content

Commit fbe46e2

Browse files
committed
Added max concurrent build option
1 parent f2f594a commit fbe46e2

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

internal/app/container/command.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
4877
func 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

78107
func (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

internal/system/config_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ func TestServerConfig(t *testing.T) {
4747
testutil.AssertEqualsInt(t, "file debounce", 300, c.System.FileWatcherDebounceMillis)
4848
testutil.AssertEqualsString(t, "node path", "", c.System.NodePath)
4949
testutil.AssertEqualsString(t, "default domain", "localhost", c.System.DefaultDomain)
50+
testutil.AssertEqualsInt(t, "max concurrent builds", 1, c.System.MaxConcurrentBuilds)
51+
testutil.AssertEqualsInt(t, "max build wait secs", 120, c.System.MaxBuildWaitSecs)
5052

5153
// Global Settings
5254
testutil.AssertEqualsString(t, "server uri", "$OPENRUN_HOME/run/openrun.sock", c.ServerUri)

internal/system/openrun.default.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ http_event_retention_days = 90 # number of days to retain http events
7171
non_http_event_retention_days = 180 # number of days to retain non-http (system, action, custom) events
7272
allowed_env = ["HOME", "OPENRUN_HOME", "PATH"] # env values allowed for use in node config
7373

74+
max_concurrent_builds = 1 # max number of concurrent container builds
75+
max_build_wait_secs = 120 # max wait time for a build lock
76+
7477
[plugin."store.in"]
7578
db_connection = "sqlite:$OPENRUN_HOME/metadata/clace_app_store.db"
7679

internal/types/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ type SystemConfig struct {
223223
AllowedEnv []string `toml:"allowed_env"` // List of environment variables that are allowed to be used in the node config
224224
DefaultScheduleMins int `toml:"default_schedule_mins"` // Default schedule time in minutes for scheduled sync
225225
MaxSyncFailureCount int `toml:"max_sync_failure_count"` // Max failure count for sync jobs
226+
MaxConcurrentBuilds int `toml:"max_concurrent_builds"` // Max concurrent container builds
227+
MaxBuildWaitSecs int `toml:"max_build_wait_secs"` // Max wait time for a build lock
226228
}
227229

228230
// GitAuth is a github auth config entry

0 commit comments

Comments
 (0)