38 lines
1.6 KiB
Go
38 lines
1.6 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/kandev/kandev/internal/common/subproc"
|
|
)
|
|
|
|
// Why this throttle exists:
|
|
//
|
|
// Before this, every code path that wanted PR status spawned its own gh
|
|
// subprocess. With ~40 active PR watches and a 30s frontend refresh, the
|
|
// background sync could fire 40-70 gh invocations within a few seconds.
|
|
// On managed corporate macOS hosts (CrowdStrike Falcon + syspolicyd code
|
|
// signing) every fork/exec is intercepted, serialized, and validated,
|
|
// which turned the burst into a multi-second exec queue. Other processes
|
|
// waiting on the same queue (new terminal shells, kandev's own gh probes)
|
|
// then hit their 30s ctx deadline and were killed, causing a feedback
|
|
// loop that effectively froze the host.
|
|
//
|
|
// The cap, env var (KANDEV_GH_MAX_CONCURRENT), and singleton live in
|
|
// internal/common/subproc so all gh callers across the backend share
|
|
// one pool. This file only wraps the package-local accessors so existing
|
|
// call sites keep their short names and so the test seam stays here.
|
|
|
|
// acquireGHSlot blocks until a gh subprocess slot is available or ctx is
|
|
// cancelled. See subproc.Throttle.Acquire for release semantics.
|
|
func acquireGHSlot(ctx context.Context) (release func(), err error) {
|
|
return subproc.GH().Acquire(ctx)
|
|
}
|
|
|
|
// setGHSemaphoreForTest replaces the gh throttle's slot pool with one of
|
|
// the given capacity and returns a restore function. Test-only — production
|
|
// code MUST NOT call this. Use cap=0 to disable throttling for a test.
|
|
func setGHSemaphoreForTest(cap int) func() {
|
|
return subproc.GH().SetCapForTest(cap)
|
|
}
|