feat(concurrency): provider-wide lens budget, drop the model cap
Concurrency was two multiplicative gates in two processes: entrypoint.sh capped MODELS-at-once per provider (GADFLY_PROVIDER_CONCURRENCY) while each model's binary separately capped its own lenses (GADFLY_LENS_CONCURRENCY). A model therefore held its whole model-slot until its LAST lens finished, stalling the next model even with idle lens capacity. Collapse to one throttle: a provider-wide lens budget shared across all of that provider's models. entrypoint now runs every model in a lane at once and seeds a single cross-process permit pool per lane (a dir of N flock files, sized by GADFLY_PROVIDER_LENS_CONCURRENCY -> GADFLY_LENS_CONCURRENCY). Each lens pass (review+recheck) acquires a permit before it runs and releases it after, so a model winding down immediately yields its freed permits to another model's queued lenses. flock auto-releases on process death, so a killed/crashed model can't leak budget. - cmd/gadfly/lenssem.go: the flock permit pool (+ lenssem_test.go). - main.go: runSpecialists holds a shared permit per lens; fanout sized to the budget so a lone model can use all of it. Falls back to the in-process limit when no pool is set (local runs, tests). - entrypoint.sh: drop provider_cap/DEFAULT_CONC; run_lane runs all models and seeds the per-lane pool. - GADFLY_PROVIDER_CONCURRENCY / GADFLY_CONCURRENCY are now ignored; the reusable workflow marks provider_concurrency deprecated and stops forwarding it. Docs (README, CLAUDE.md, examples) updated per the maintenance rule. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
@@ -44,7 +44,7 @@ on:
|
||||
#
|
||||
# Owner-set user-scope variables (see README "Central config via variables"):
|
||||
# GADFLY_DEFAULT_MODELS, GADFLY_DEFAULT_SPECIALISTS,
|
||||
# GADFLY_DEFAULT_PROVIDER_CONCURRENCY, GADFLY_DEFAULT_PROVIDER_LENS_CONCURRENCY,
|
||||
# GADFLY_DEFAULT_PROVIDER_LENS_CONCURRENCY (the provider-wide lens budget),
|
||||
# GADFLY_ENDPOINT_NETHERSTORM (the local GPU box endpoint).
|
||||
# An unset variable + no input → the image default (one model, default suite),
|
||||
# so a public consumer with neither still gets a sane minimal review.
|
||||
@@ -53,8 +53,8 @@ on:
|
||||
specialists: { type: string, default: "" } # GADFLY_SPECIALISTS — empty falls back to user var GADFLY_DEFAULT_SPECIALISTS
|
||||
provider: { type: string, default: "" } # GADFLY_PROVIDER
|
||||
base_url: { type: string, default: "" } # GADFLY_BASE_URL
|
||||
provider_concurrency: { type: string, default: "" } # GADFLY_PROVIDER_CONCURRENCY — empty falls back to user var GADFLY_DEFAULT_PROVIDER_CONCURRENCY
|
||||
provider_lens_concurrency: { type: string, default: "" } # GADFLY_PROVIDER_LENS_CONCURRENCY — empty falls back to user var GADFLY_DEFAULT_PROVIDER_LENS_CONCURRENCY
|
||||
provider_concurrency: { type: string, default: "" } # DEPRECATED / ignored — the per-provider MODEL cap was removed; the lens budget below is the single throttle. Kept so existing callers don't error.
|
||||
provider_lens_concurrency: { type: string, default: "" } # GADFLY_PROVIDER_LENS_CONCURRENCY — the per-provider lens budget (shared across the provider's models); empty falls back to user var GADFLY_DEFAULT_PROVIDER_LENS_CONCURRENCY
|
||||
timeout_secs: { type: string, default: "600" } # GADFLY_TIMEOUT_SECS (per lens)
|
||||
max_steps: { type: string, default: "14" } # GADFLY_MAX_STEPS
|
||||
worker_model: { type: string, default: "" } # GADFLY_WORKER_MODEL
|
||||
@@ -151,7 +151,9 @@ jobs:
|
||||
GADFLY_SPECIALISTS: ${{ inputs.specialists || vars.GADFLY_DEFAULT_SPECIALISTS }}
|
||||
GADFLY_PROVIDER: ${{ inputs.provider }}
|
||||
GADFLY_BASE_URL: ${{ inputs.base_url }}
|
||||
GADFLY_PROVIDER_CONCURRENCY: ${{ inputs.provider_concurrency || vars.GADFLY_DEFAULT_PROVIDER_CONCURRENCY }}
|
||||
# NB: GADFLY_PROVIDER_CONCURRENCY (the old model cap) is intentionally no
|
||||
# longer forwarded — entrypoint.sh ignores it. The lens budget is the one
|
||||
# throttle now, shared across a provider's models.
|
||||
GADFLY_PROVIDER_LENS_CONCURRENCY: ${{ inputs.provider_lens_concurrency || vars.GADFLY_DEFAULT_PROVIDER_LENS_CONCURRENCY }}
|
||||
GADFLY_TIMEOUT_SECS: ${{ inputs.timeout_secs }}
|
||||
GADFLY_MAX_STEPS: ${{ inputs.max_steps }}
|
||||
|
||||
Reference in New Issue
Block a user