Cap concurrent calls to PESU Academy and add a circuit breaker
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
Direzione di ricerca
Read CONTRIBUTING.md first, then inspect _upstream_call and authenticate in app/pesu.py, plus the existing exception and metric patterns. Define and test the breaker in app/resilience.py with an injected clock, then cover bulkhead and refresh behavior before updating README and app/docs/authenticate.py; tests/unit/test_openapi_docs.py must pass and the live credentialed suite must succeed.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
🔄 Updated for v5.0.0 (2026-10-08). pesu-auth now signs in through PESU Academy's mobile API (#241): a login is at most two upstream calls (
loginandprofile_fetch), and the CSRF prefetch and refresh loop are gone. The bulkhead and breaker are still wanted; the parts that relied on background calls (the refresh as a free health probe) are removed, and what counts as a failure is restated for the new responses.
⚠️ PES University students only. This change sits in the login path and has to be tested end to end against PESU Academy with real PESU credentials (see "Tests that need credentials" in
CONTRIBUTING.md). Run the whole suite with your credentials in.envand paste the summary line into your PR. Every run makes real logins to PESU Academy, so run it when you need it, not in a loop.
Summary
When PESU Academy is slow or down, pesu-auth keeps sending it every request, and every caller waits for the full timeout before failing. Add two standard resilience patterns around the upstream calls:
- A bulkhead: a cap on how many logins talk to PESU Academy at once, so a traffic spike can't pile up hundreds of slow requests (and hundreds of open clients) in one process.
- A circuit breaker: after repeated upstream failures, fail fast with 503 and
Retry-Afterfor a short cool-down instead of waiting on a service that is known to be down, then let a trial request through to check whether it has recovered.
Background
- Every upstream request goes through
_upstream_call(app/pesu.py), which already classifies each call assuccess,errororcancelled. It treats "no exception" as success, so a 5xx response counts as success there; see #170 for the same distinction. - The client timeout is 10 s per call (
UPSTREAM_TIMEOUT_SECONDSinapp/pesu.py), and a login makes up to 2 calls:login, thenprofile_fetchwhen the profile is requested. Each login gets its ownhttpx2.AsyncClient, closed before it returns. - pesu-auth is one process on Render's free tier, so all state here is in memory and per process. Say so in comments.
Proposed change
Bulkhead
- An
asyncio.SemaphoreinPESUAcademy, sized by a constant (for example 20) with a comment explaining the choice, acquired for the whole ofauthenticate. - If no permit is free within a short wait (for example 2 s), fail with 503 and
Retry-After, rather than queueing indefinitely. - Since 5.0.0 there is no background work (the CSRF prefetch and refresh loop are gone), so every upstream call belongs to a request and goes through the bulkhead.
Circuit breaker
- States: closed (normal), open (fail fast), and half-open (one trial request).
- Opening: N consecutive upstream failures (for example 5) open the circuit for a cool-down (for example 30 s). A failure is an exception or a 5xx response from either operation (
login,profile_fetch). A 4xx and a wrong password (PESU's401) are not failures;cancelledis ignored. Neither is an HTTP 200 carrying PESU's error envelope, such as the profile call's{"status": 403, "message": "Access Denied"}for a non-student account: PESU answered. - While open,
authenticateraises a newPESUAcademyErrorsubclass straight away (status 503, headerRetry-After: <remaining seconds>, message "PESU Academy is currently unavailable. Please try again later."). Put the header on the exception likeMetricsAuthorizationErrordoes, and the existing handler will pass it through. - Half-open: after the cool-down, exactly one request is let through. A success closes the circuit; a failure opens it again.
- Nothing calls PESU in the background any more, so while the circuit is open nothing probes it; the half-open trial request is the only probe. Say so in a comment.
- Keep the breaker in a small class of its own (for example in
app/resilience.py), with its own unit tests, and inject a clock so the tests don't sleep.
Observability and docs
- A gauge for breaker state (0 closed, 1 half-open, 2 open) and a counter of rejections, following the
add-metricskill. The exception class already lands inerrors_total{type}. - The README's
/authenticateresponses table gets a 503 row, andapp/docs/authenticate.pygets a 503 example (tests/unit/test_openapi_docs.pyenforces that the examples match).
Tests
- The breaker class: opens after N failures, rejects while open, lets exactly one trial through when half-open, closes on success, re-opens on failure; 4xx and cancellation don't count.
-
authenticatereturns 503 withRetry-Afterwhile open. - The bulkhead rejects with 503 when saturated, and releases permits on every path, including exceptions and cancellation.
- A wrong password (401) and an HTTP 200 error envelope never count as failures.
- The live suite passes.
Acceptance criteria
- With PESU down, callers get a fast 503 with
Retry-Afterinstead of waiting 10–20 s - The service recovers on its own when PESU does
- No more than the configured number of logins talk to PESU at once
- Metrics, README and OpenAPI examples are updated
Related
- #184 (504 for timeouts; since 5.0.0 a transport error is already a 502,
UpstreamErrororProfileFetchError) and #185 (timeouts) define the per-request failures this breaker counts. - #170 records when PESU last succeeded and failed; share the definition of "failure".
How to contribute
- Wait until you're assigned. Comment to ask for this issue, then wait for a maintainer to assign it to you before writing any code. PRs for unassigned issues are closed without review.
- Read
CONTRIBUTING.mdfirst. It covers forking, setting up withuv, and running the tests. - Branch from
devin your fork, and open the PR againstdevwith a Conventional Commit title andCloses #183in the description. - Bump the minor version in
pyproject.tomland runuv lock(CI checks this).uv run pre-commit run --all-filesmust pass, and coverage must stay at 100%. - Update the README,
app/docs/and comments in the same PR as the behaviour they describe. - Never log, print, store or echo a password or token, including in tests, PR descriptions and screenshots.
- Lingua principale
- Python
- Stelle
- 22
- Fork
- 29
- Merge medio
- 1g 3h
- PR unite (30g)
- 19
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di pesu-dev/auth
-
Check the README for dead links and fix the misleading Docker Hub badgeForse di nuovo libera @knownshah l’ha presa 18 giorni fa e non c’è nessuna pull request aperta. Apertadocumentation good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
pesu-dev/auth#220 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
bug documentation enhancement
Difficoltà 3/5 1-2 giorni Idoneità per principianti 54/100
I maintainer di solito rispondono entro 1 giorno
-
Commit SHA should be used instead of tag git based deployForse già presa @aditeyabaral l’ha presa 12 giorni fa. Apertabug
pesu-dev/auth#236 · 2 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Private Functions in `app.py` needs to be in separate fileForse già presa @aditeyabaral l’ha presa 12 giorni fa. Apertaapi enhancement
pesu-dev/auth#235 · 1 commento · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
Gather the campus mapping and other shared values into constants modulesForse già presa @edgelordlinux l’ha presa 12 giorni fa. Apertaapi enhancement good first issue pesuacademy student profile tests and ci/cd
pesu-dev/auth#230 · 3 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di pesu-dev/auth
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
UKGovernmentBEIS/control-arena#917 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
debpalash/VoiceStudio#2937 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
aws-samples/sample-per-model-bedrock#261 ·
I maintainer di solito rispondono entro 1 giorno