Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 24 additions & 9 deletions packages/orchestrator/pkg/sandbox/build/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package build
import (
"context"
"fmt"
"math"
"os"
"sync"
"time"
Expand Down Expand Up @@ -222,15 +223,7 @@ func (s *DiffStore) startDiskSpaceEviction(
used := int64(dUsed) - pUsed
percentage := float64(used) / float64(dTotal) * 100

threshold := featureflags.BuildCacheMaxUsagePercentage.Fallback()
// When multiple services (template manager, orchestrator) are defined, take the lowest threshold
// to ensure we don't exceed any of the set limits
for _, s := range services {
st := flags.IntFlag(ctx, featureflags.BuildCacheMaxUsagePercentage, featureflags.ServiceContext(string(s)))
if st < threshold {
threshold = st
}
}
threshold := evictionThreshold(ctx, flags, services)

if percentage <= float64(threshold) {
timer.Reset(getDelay(false))
Expand All @@ -252,6 +245,28 @@ func (s *DiffStore) startDiskSpaceEviction(
}
}

// evictionThreshold returns the maximum allowed disk usage percentage for the
// build cache. When multiple services (template manager, orchestrator) are
// defined, the lowest of their configured thresholds wins to ensure none of
// the set limits is exceeded. Flag evaluation already falls back per service
// inside IntFlag, so the flag fallback is only used directly when no services
// are configured; a flag value above the fallback is honored.
func evictionThreshold(ctx context.Context, flags *featureflags.Client, services cfg.Services) int {
if len(services) == 0 {
return featureflags.BuildCacheMaxUsagePercentage.Fallback()
}

threshold := math.MaxInt
for _, svc := range services {
st := flags.IntFlag(ctx, featureflags.BuildCacheMaxUsagePercentage, featureflags.ServiceContext(string(svc)))
if st < threshold {
threshold = st
}
}

return threshold
}

func (s *DiffStore) getPendingDeletesSize() int64 {
s.pdMu.RLock()
defer s.pdMu.RUnlock()
Expand Down
53 changes: 53 additions & 0 deletions packages/orchestrator/pkg/sandbox/build/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,59 @@ func TestDiffStoreResetDeleteRace(t *testing.T) {
time.Sleep(delay * 2)
}

func TestEvictionThreshold(t *testing.T) {
t.Parallel()

t.Run("no services falls back", func(t *testing.T) {
t.Parallel()

flags := flagsWithMaxBuildCachePercentage(t, 95)

got := evictionThreshold(t.Context(), flags, nil)
assert.Equal(t, featureflags.BuildCacheMaxUsagePercentage.Fallback(), got)
})

t.Run("flag can raise threshold above fallback", func(t *testing.T) {
t.Parallel()

flags := flagsWithMaxBuildCachePercentage(t, 95)

got := evictionThreshold(t.Context(), flags, cfg.Services{cfg.Orchestrator})
assert.Equal(t, 95, got)
})

t.Run("flag can lower threshold below fallback", func(t *testing.T) {
t.Parallel()

flags := flagsWithMaxBuildCachePercentage(t, 10)

got := evictionThreshold(t.Context(), flags, cfg.Services{cfg.Orchestrator})
assert.Equal(t, 10, got)
})

t.Run("lowest service threshold wins", func(t *testing.T) {
t.Parallel()

datastore := ldtestdata.DataSource()
datastore.Update(
datastore.Flag(featureflags.BuildCacheMaxUsagePercentage.String()).
Variations(ldvalue.Int(95), ldvalue.Int(40)).
VariationIndexForKey(featureflags.ServiceKind, string(cfg.Orchestrator), 0).
VariationIndexForKey(featureflags.ServiceKind, string(cfg.TemplateManager), 1).
FallthroughVariationIndex(0),
)

flags, err := featureflags.NewClientWithDatasource(datastore)
require.NoError(t, err)
t.Cleanup(func() {
assert.NoError(t, flags.Close(t.Context()))
})

got := evictionThreshold(t.Context(), flags, cfg.Services{cfg.Orchestrator, cfg.TemplateManager})
assert.Equal(t, 40, got)
})
}

func flagsWithMaxBuildCachePercentage(tb testing.TB, maxBuildCachePercentage int) *featureflags.Client {
tb.Helper()

Expand Down
Loading