frockemon_generator / fallback.py
tikatakatoe56-rgb
Serve a refused GPU booking from Inference Providers
f522eb6
Raw History Blame Contribute Delete
2.21 kB
"""Serve a refused GPU booking from Inference Providers instead.
ZeroGPU refuses a booking *before* it runs the callback: the scheduler checks
the requested duration against the visitor's remaining quota and raises, so
nothing has happened yet and the same call can simply be made somewhere else.
That is the whole reason this is safe to retry - a failure raised from inside
a running callback must not be retried, because half the work is already done
and `accept` writes files and opens a pull request.
So the test is deliberately narrow: only the messages ZeroGPU produces at
admission, and only when the operator has set a spending ceiling, which is
what turns the fallback on. Everything else is re-raised untouched.
"""
import functools
# All raised by spaces.zero.client.schedule() before the callback is invoked.
ADMISSION_REFUSALS = (
"is larger than the maximum allowed",
"exceeded your zerogpu",
"exceeded your pro zerogpu",
"exceeded your free zerogpu",
"exceeded your zerogpu runs limit",
"has reached its gpu limit",
"no gpu was available",
"too many zerogpu credits allocated",
)
def is_admission_refusal(exc):
"""True only for a refusal raised before the callback body ran."""
text = str(exc).lower()
return any(phrase in text for phrase in ADMISSION_REFUSALS)
def guarded(plain, booked, enabled, enter, leave, log):
"""`booked` first; on an admission refusal, `plain` between enter/leave.
functools.wraps is load-bearing rather than tidy: Gradio decides whether
to inject a gr.OAuthProfile by reading the callback's annotations and
signature, and an unwrapped *args/**kwargs shim would hide both and quietly
sign every visitor out - the failure this app has already had once.
"""
@functools.wraps(plain)
def run(*args, **kwargs):
try:
return booked(*args, **kwargs)
except Exception as exc: # noqa: BLE001
if not (enabled() and is_admission_refusal(exc)):
raise
log(exc)
enter()
try:
return plain(*args, **kwargs)
finally:
leave()
return run