Polling¶
Pass a timeout to a client verb and the verb polls until a success status arrives.
Consumers who want polling as a separate step use the poll routine from the
resq.http surface on an already-built response wrapper.
poll operates on an already-built wrapper — it never issues the first request and
never references a client or adapter. It calls raise_for_status to check the status.
On a bad status, it retries through the wrapper's own reload until success or until
the timeout window elapses. The mode (sync/async) is determined by the wrapper's type:
a Response runs a sync loop; an AsyncResponse runs an async loop (await it).
The easy way — a verb with a timeout¶
Most consumers never call poll themselves: passing a timeout to a client verb makes
the verb poll internally and return the already-polled wrapper.
Sync poll¶
Build the primary response with a non-polling verb (timeout left at None), then poll
it as a separate call:
from resq import Requests
from resq.http import poll
client = Requests("https://api.example.com", adapter="requests", timeout=5)
r = client.get("/job/42") # single request, a Response
r = poll(r, timeout=30, delay=2) # poll up to 30s, 2s apart
The same r object is returned; its underlying is refreshed in place on each retry.
Async poll¶
from resq import Requests
from resq.http import poll
async with Requests("https://api.example.com", adapter="httpx", timeout=5) as client:
r = await client.get("/job/42") # single request, an AsyncResponse
r = await poll(r, timeout=30, delay=2) # poll up to 30s, 2s apart
When you do not need poll directly¶
Reach for poll directly only when the primary request and the polling loop must be
separate steps — for example, inspecting the primary response before deciding to poll,
or polling a wrapper obtained from elsewhere.
Handling exhaustion¶
If the window elapses without a success-status response, the LAST response is returned
(its status is the final non-2xx). No exception is raised — inspect ok /
status_code, or call reload to retry:
r = poll(r, timeout=30, delay=2)
if not r.ok:
... # window elapsed, last status non-2xx
r.reload() # sync; await r.reload() for an AsyncResponse
Behavior & preconditions¶
timeoutis the polling window in seconds, measured from the start of the call (not per attempt).Nonedisables polling and returns the wrapper unchanged with no status check.delaysets the seconds between attempts and is ignored whentimeoutisNone. The client verbs default it to1.0; when callingpolldirectly, pass it explicitly.- Polling retries only on a bad status — whatever
raise_for_statusraises on the engine: 4xx/5xx forrequests; any non-2xx forhttpx, including unfollowed 3xx such as 304. Transport-level failures (connection, TLS, read-timeout) propagate immediately and are not retried. polldoes not raise on window expiry; it returns the last response.- The mode is fixed by the wrapper's type — a sync
Responseyields a sync loop, anAsyncResponseyields an async loop (await the call andreload).