mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-10 11:20:02 +00:00
perf(actions): debounce runner heartbeat writes and throttle task picks (#38281)
3 reductions in the DB load generated by many runners polling `FetchTask`: **1. Debounce runner heartbeat writes** Every poll wrote `last_online`, and every `UpdateTask`/`UpdateLog` wrote `last_active` — while a runner streams logs that is many writes per second per runner. These are now persisted only when stale enough to actually affect the active/offline status (`ShouldPersistLastOnline` / `ShouldPersistLastActive`), using the existing columns. **2. Throttle concurrent task picks** A new in-process semaphore (`MAX_CONCURRENT_TASK_PICKS`) bounds how many runners run the task-assignment transaction at once, so a fleet polling together cannot stampede the query. Throttled polls retry on their next poll without advancing the runner's tasks version. **3. Paginate the task-pick query** `CreateTaskForRunner` previously loaded every waiting job in the runner's scope into memory on each poll (no `LIMIT`). Now it pages through the waiting backlog oldest-first with `LIMIT`, claiming the first label-matching job. --------- Co-authored-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
@@ -14,6 +14,8 @@ import (
|
||||
|
||||
const defaultMaxRerunAttempts = 50
|
||||
|
||||
const defaultMaxConcurrentTaskPicks = 16
|
||||
|
||||
// Actions settings
|
||||
var (
|
||||
Actions = struct {
|
||||
@@ -31,13 +33,18 @@ var (
|
||||
WorkflowDirs []string `ini:"WORKFLOW_DIRS"`
|
||||
ScopedWorkflowDirs []string `ini:"SCOPED_WORKFLOW_DIRS"`
|
||||
MaxRerunAttempts int64 `ini:"MAX_RERUN_ATTEMPTS"`
|
||||
// MaxConcurrentTaskPicks bounds how many runners may run the task-assignment
|
||||
// transaction at once per Gitea instance, to avoid a thundering herd when many
|
||||
// runners poll together. It is a per-process limit, not a cluster-wide one.
|
||||
MaxConcurrentTaskPicks int `ini:"MAX_CONCURRENT_TASK_PICKS"`
|
||||
}{
|
||||
Enabled: true,
|
||||
DefaultActionsURL: defaultActionsURLGitHub,
|
||||
SkipWorkflowStrings: []string{"[skip ci]", "[ci skip]", "[no ci]", "[skip actions]", "[actions skip]"},
|
||||
WorkflowDirs: []string{".gitea/workflows", ".github/workflows"},
|
||||
ScopedWorkflowDirs: []string{".gitea/scoped_workflows"},
|
||||
MaxRerunAttempts: defaultMaxRerunAttempts,
|
||||
Enabled: true,
|
||||
DefaultActionsURL: defaultActionsURLGitHub,
|
||||
SkipWorkflowStrings: []string{"[skip ci]", "[ci skip]", "[no ci]", "[skip actions]", "[actions skip]"},
|
||||
WorkflowDirs: []string{".gitea/workflows", ".github/workflows"},
|
||||
ScopedWorkflowDirs: []string{".gitea/scoped_workflows"},
|
||||
MaxRerunAttempts: defaultMaxRerunAttempts,
|
||||
MaxConcurrentTaskPicks: defaultMaxConcurrentTaskPicks,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -128,6 +135,10 @@ func loadActionsFrom(rootCfg ConfigProvider) error {
|
||||
Actions.MaxRerunAttempts = defaultMaxRerunAttempts
|
||||
}
|
||||
|
||||
if Actions.MaxConcurrentTaskPicks <= 0 {
|
||||
Actions.MaxConcurrentTaskPicks = defaultMaxConcurrentTaskPicks
|
||||
}
|
||||
|
||||
if !Actions.LogCompression.IsValid() {
|
||||
return fmt.Errorf("invalid [actions] LOG_COMPRESSION: %q", Actions.LogCompression)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user