Commit 50e9dba

Eric Bower  ·  2026-08-15 14:08:35 -0400 EDT
parent eb0002c
fix(gc): wait 3 hours before killing sessions
2 files changed,  +29, -26
+21, -19
......@@ -2215,16 +2215,15 @@ func cancelJobSessions(prefix string) {
22152215 }
22162216 }
22172217
2218-// findSessionsForGC identifies finished sessions or sessions older than 3 hours matching given prefixes.
2219-// It checks whether a session's job has an active runner session (a .runner session with Ended == "");
2220-// if so, finished child sessions for that job are NOT cleaned up yet to ensure no new tasks spawn
2221-// in pico.sh before cleaning up tasks.
2218+// findSessionsForGC identifies finished or running sessions older than the retention cutoff (3 hours) matching given prefixes.
2219+// It checks whether a session's job has an active session; active jobs are preserved unless their sessions have expired.
2220+// Finished sessions are kept until they are older than the cutoff so users can inspect/debug test failures.
22222221 func findSessionsForGC(sessions []SessionInfo, prefixes []string, now time.Time) []string {
22232222 cutoff := now.Add(-3 * time.Hour).Unix()
22242223
22252224 // Track which job prefixes have ANY active (running) session.
22262225 // As long as any session for a job is still running (Ended == ""),
2227- // the job is active and none of its sessions should be garbage collected.
2226+ // the job is active and none of its sessions should be garbage collected unless expired.
22282227 activeJobPrefixes := make(map[string]bool)
22292228 for _, s := range sessions {
22302229 if s.Ended == "" {
......@@ -2248,7 +2247,7 @@ func findSessionsForGC(sessions []SessionInfo, prefixes []string, now time.Time)
22482247 continue
22492248 }
22502249
2251- // If the session belongs to a job with an active runner, do not kill it
2250+ // If the session belongs to a job with an active session, do not kill it
22522251 // unless it has expired (> 3 hours old).
22532252 jobPrefix := extractJobPrefix(s.Name)
22542253 if jobPrefix != "" && activeJobPrefixes[jobPrefix] {
......@@ -2264,22 +2263,25 @@ func findSessionsForGC(sessions []SessionInfo, prefixes []string, now time.Time)
22642263 continue
22652264 }
22662265
2266+ // For completed/inactive jobs, only kill sessions if they ended or were created before the cutoff
22672267 if s.Ended != "" {
2268- toKill = append(toKill, s.Name)
2269- continue
2270- }
2271-
2272- if s.Created == "" {
2273- continue
2274- }
2275-
2276- var created int64
2277- if _, err := fmt.Sscanf(s.Created, "%d", &created); err != nil {
2278- continue
2268+ var ended int64
2269+ if _, err := fmt.Sscanf(s.Ended, "%d", &ended); err == nil {
2270+ if ended < cutoff {
2271+ toKill = append(toKill, s.Name)
2272+ }
2273+ continue
2274+ }
22792275 }
22802276
2281- if created < cutoff {
2282- toKill = append(toKill, s.Name)
2277+ if s.Created != "" {
2278+ var created int64
2279+ if _, err := fmt.Sscanf(s.Created, "%d", &created); err != nil {
2280+ continue
2281+ }
2282+ if created < cutoff {
2283+ toKill = append(toKill, s.Name)
2284+ }
22832285 }
22842286 }
22852287 return toKill
+8, -7
......@@ -706,9 +706,11 @@ func TestFindSessionsForGC(t *testing.T) {
706706
707707 sessions := []SessionInfo{
708708 {Name: "ci.repo.active.runner", Created: twoHoursAgo, Ended: ""},
709- {Name: "ci.repo.active.step.fmt", Created: twoHoursAgo, Ended: "1786289500"},
710- {Name: "ci.repo.finished.runner", Created: twoHoursAgo, Ended: "1786289600"},
711- {Name: "ci.repo.finished.step.lint", Created: twoHoursAgo, Ended: "1786289550"},
709+ {Name: "ci.repo.active.step.fmt", Created: twoHoursAgo, Ended: twoHoursAgo},
710+ {Name: "ci.repo.recent.runner", Created: twoHoursAgo, Ended: twoHoursAgo},
711+ {Name: "ci.repo.recent.step.lint", Created: twoHoursAgo, Ended: twoHoursAgo},
712+ {Name: "ci.repo.oldfinished.runner", Created: fourHoursAgo, Ended: fourHoursAgo},
713+ {Name: "ci.repo.oldfinished.step.lint", Created: fourHoursAgo, Ended: fourHoursAgo},
712714 {Name: "ci.repo.expired.runner", Created: fourHoursAgo, Ended: ""},
713715 {Name: "other.session", Created: fourHoursAgo, Ended: ""},
714716 }
......@@ -718,9 +720,9 @@ func TestFindSessionsForGC(t *testing.T) {
718720 t.Fatalf("expected 3 sessions for GC, got %d: %v", len(toKill), toKill)
719721 }
720722 expected := map[string]bool{
721- "ci.repo.finished.runner": true,
722- "ci.repo.finished.step.lint": true,
723- "ci.repo.expired.runner": true,
723+ "ci.repo.oldfinished.runner": true,
724+ "ci.repo.oldfinished.step.lint": true,
725+ "ci.repo.expired.runner": true,
724726 }
725727 for _, k := range toKill {
726728 if !expected[k] {
......@@ -1495,4 +1497,3 @@ func TestFindSSHAuthMethod_ExplicitKeyAndCert(t *testing.T) {
14951497 t.Fatal("expected error when non-existent certificate is explicitly specified")
14961498 }
14971499 }
1498-