• Stefy Lanza (nextime / spora )'s avatar
    runpod: a fleet that grew for a burst has to give the pods back (v0.3.11) · de706ddb
    Stefy Lanza (nextime / spora ) authored
    Only half the scaler existed. The pool adds a pod once every pod it has carries
    scale_up_inflight_per_pod requests, and pods went away again only through the
    idle reaper — which fires on a pod with NO work and no request for
    idle_timeout_s.
    
    That misses the expensive case. A pool that grew for a burst and is now serving
    a trickle keeps every pod: each is touched often enough that last_used never
    ages out, each is a fraction busy, and the bill stays at the peak for as long as
    the trickle lasts. With max_pods raised to 64 that is the difference between a
    few dollars an hour and a few hundred.
    
    So the pool also asks how many pods the CURRENT concurrency justifies and
    retires the excess. The rules that matter are not "fewer pods":
    
      * work is never dropped to save money. The pod retired is the least loaded,
        and if it still has requests it is marked draining — no new work, and
        terminated only once it has finished what it had;
      * one pod per pass, after the surplus has persisted for scale_down_after_s,
        and the window restarts after each retirement. A dip of a few seconds must
        not cost a pod wanted again seconds later: a cold one takes minutes;
      * a quiet pool is NOT this routine's business. With nothing in flight,
        teardown stays entirely with idle_timeout_s — a number the operator chose,
        weighing the bill against a cold start — so this never silently shortens it.
    
    A draining pod is also excluded from the growth decision, which reads the LEAST
    loaded pod: an emptying drainer would otherwise answer "no need to grow" with
    the one pod that cannot take the work.
    
    Two existing tests had to change. A _Pod stub stood in for PodHandle without
    the new field, and a source-text assertion used a 600-character window that a
    new field plus its comment pushed data_center out of — now asserted against the
    whole class, which is what it was always about.
    Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01PxYHWbCAjjjD7A1rhFKtaW
    de706ddb
Name
Last commit
Last update
..
admin Loading commit data...
api Loading commit data...
backends Loading commit data...
broker Loading commit data...
cluster Loading commit data...
compose Loading commit data...
frontproxy Loading commit data...
models Loading commit data...
ocr Loading commit data...
openai Loading commit data...
pydantic Loading commit data...
queue Loading commit data...
tasks Loading commit data...
util Loading commit data...
__init__.py Loading commit data...
cli.py Loading commit data...
config.py Loading commit data...
main.py Loading commit data...
platform_paths.py Loading commit data...
system_app.py Loading commit data...