mirror of
https://gitea.com/gitea/runner.git
synced 2026-11-12 02:44:10 +00:00
enhance: make shared tool cache safe at any capacity (#1401)
Co-authored-by: bircni <[email protected]>
This commit is contained in:
1 parent
84c0fcd1fa
commit
a021d3139d
9 files changed
+121
-11
No files matched your search
@@ -79,6 +79,7 @@ type Runner struct {
|
||||
runningTasks sync.Map
|
||||
runningCount atomic.Int64
|
||||
lastIdleCleanupUnixNano atomic.Int64
|
||||
slots slotAllocator
|
||||
now func() time.Time
|
||||
healthCheckLast time.Time
|
||||
healthCheckReady bool
|
||||
@@ -451,6 +452,9 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
||||
}
|
||||
}()
|
||||
|
||||
slot := r.slots.acquire()
|
||||
defer r.slots.release(slot)
|
||||
|
||||
workflowCallInputs := restoreCalledWorkflowContext(task)
|
||||
for _, line := range r.setupLines(task) {
|
||||
reporter.Logf("%s", line)
|
||||
@@ -623,6 +627,7 @@ func (r *Runner) run(ctx context.Context, task *runnerv1.Task, reporter *report.
|
||||
ValidVolumes: r.cfg.Container.ValidVolumes,
|
||||
ContainerVolumes: r.cfg.Container.Volumes,
|
||||
SharedToolCache: r.cfg.Runner.ToolCacheMode == config.ToolCacheModeShared,
|
||||
ToolCacheSlot: toolCacheSlot(r.cfg.Runner.ToolCacheMode, slot),
|
||||
InsecureSkipTLS: r.cfg.Runner.Insecure,
|
||||
ClientCertFile: r.cfg.Runner.ClientCertFile,
|
||||
ClientKeyFile: r.cfg.Runner.ClientKeyFile,
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package run
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"gitea.com/gitea/runner/internal/pkg/config"
|
||||
)
|
||||
|
||||
// slotAllocator hands out the lowest free slot, so slot numbers stay below capacity.
|
||||
type slotAllocator struct {
|
||||
mu sync.Mutex
|
||||
used []bool
|
||||
}
|
||||
|
||||
func (a *slotAllocator) acquire() int {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
slot := slices.Index(a.used, false)
|
||||
if slot < 0 {
|
||||
slot = len(a.used)
|
||||
a.used = append(a.used, false)
|
||||
}
|
||||
a.used[slot] = true
|
||||
return slot
|
||||
}
|
||||
|
||||
func (a *slotAllocator) release(slot int) {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
a.used[slot] = false
|
||||
}
|
||||
|
||||
// toolCacheSlot leaves slot 0 unnamed, so it keeps the cache a runner had before slots existed.
|
||||
func toolCacheSlot(mode string, slot int) string {
|
||||
if mode != config.ToolCacheModeShared || slot == 0 {
|
||||
return ""
|
||||
}
|
||||
return strconv.Itoa(slot)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package run
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.com/gitea/runner/internal/pkg/config"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestToolCacheSlotReusesLowestFree(t *testing.T) {
|
||||
var slots slotAllocator
|
||||
require.Equal(t, 0, slots.acquire())
|
||||
require.Equal(t, 1, slots.acquire())
|
||||
require.Equal(t, 2, slots.acquire())
|
||||
slots.release(1)
|
||||
assert.Equal(t, 1, slots.acquire())
|
||||
assert.Equal(t, 3, slots.acquire())
|
||||
|
||||
assert.Equal(t, "3", toolCacheSlot(config.ToolCacheModeShared, 3))
|
||||
assert.Empty(t, toolCacheSlot(config.ToolCacheModeShared, 0))
|
||||
assert.Empty(t, toolCacheSlot(config.ToolCacheModeNone, 3))
|
||||
}
|
||||
Reference in new issue
Block a user