3 Commits
Author SHA1 Message Date
dsql 83a156fd31 fix: forward per-request timeout to geo lookups on an injected session
_get_json applied the timeout only when it created the session; when the caller passed their own session=, the timeout was silently dropped and the session default (aiohttp's 300s) governed. the per-request timeout is now passed to session.get(timeout=...) on both the owned and injected paths.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-29 01:10:25 -04:00
dsql de6911fb05 fix: retry log uses total attempts as the denominator
the retry warning logged index/last_index (attempts-1), so a 3-attempt retry showed 'retry 1/2'. now logs index+1 of attempts. both retry and aretry.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-28 17:18:28 -04:00
dsql c6e3dd1b54 fix: floor retry/aretry attempts at 1 (v0.2.1)
retry(fn, attempts=0) (or negative) silently returned None without ever calling fn,
looking like success. floor attempts at max(1, attempts) so the callable always runs
at least once; a failing call now fails loud after one try instead of no-op None.

verified: attempts=0/-5 -> 1 call (sync + async); failing fn raises after 1 try;
31/31 retry regression intact.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-28 16:11:34 -04:00
5 changed files with 12 additions and 7 deletions
+2 -2
View File
@@ -12,9 +12,9 @@ Small sync helpers shared across projects. Base is stdlib only — **no dependen
## Install
```
commons @ git+ssh://git@git.rethinkstudios.io/rethink-public/commons.git@v0.2.0
commons @ git+ssh://git@git.rethinkstudios.io/rethink-public/commons.git@v0.2.1
# async address/geo lookups (fetch_ip / ip_location / fetch_location) need the extra:
commons[addr] @ git+ssh://git@git.rethinkstudios.io/rethink-public/commons.git@v0.2.0
commons[addr] @ git+ssh://git@git.rethinkstudios.io/rethink-public/commons.git@v0.2.1
```
The base install pulls **nothing** (stdlib). Only `commons[addr]` adds `aiohttp`, and
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "commons"
version = "0.2.0"
version = "0.2.1"
description = "small stdlib-only sync helpers: time/timezone deltas, dotted-path dict access, display masking, ip/address tooling, and retry/backoff"
requires-python = ">=3.10"
dependencies = []
+1 -1
View File
@@ -63,4 +63,4 @@ __all__ = [
"aretry",
]
__version__ = "0.2.0"
__version__ = "0.2.1"
+2 -1
View File
@@ -80,7 +80,8 @@ async def _get_json(
if owns:
session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=timeout))
try:
async with session.get(url, headers=headers) as resp:
request_timeout = aiohttp.ClientTimeout(total=timeout)
async with session.get(url, headers=headers, timeout=request_timeout) as resp:
if resp.status != 200:
log.warning("address lookup %s -> %s", url, resp.status)
return None
+6 -2
View File
@@ -77,8 +77,10 @@ def retry(
`retry(fn, ...)` runs immediately; `@retry(...)` wraps a function. retries on the
`on` exceptions, stops early if `give_up(exc)` is true, re-raises the last
exception once `attempts` are exhausted. `sleep`/`rand` are injectable for tests.
`attempts` is floored at 1 so the callable always runs at least once.
"""
types = _as_types(on)
attempts = max(1, attempts)
def run(target: Callable, args, kwargs):
delays = list(_delays(attempts, backoff, factor, max_backoff))
@@ -94,7 +96,7 @@ def retry(
wait = _jittered(delays[index], jitter, rand)
log.warning(
"retry %d/%d after %s: %s",
index + 1, last_index, type(exc).__name__, exc,
index + 1, attempts, type(exc).__name__, exc,
)
if wait > 0:
sleep(wait)
@@ -128,8 +130,10 @@ def aretry(
async twin of `retry`. `await aretry(coro_fn, ...)` runs immediately;
`@aretry(...)` wraps a coroutine function. same semantics: retry on `on`, stop on
`give_up`, re-raise the last exception after `attempts`. `sleep`/`rand` injectable.
`attempts` is floored at 1 so the callable always runs at least once.
"""
types = _as_types(on)
attempts = max(1, attempts)
async def run(target: Callable, args, kwargs):
delays = list(_delays(attempts, backoff, factor, max_backoff))
@@ -145,7 +149,7 @@ def aretry(
wait = _jittered(delays[index], jitter, rand)
log.warning(
"retry %d/%d after %s: %s",
index + 1, last_index, type(exc).__name__, exc,
index + 1, attempts, type(exc).__name__, exc,
)
if wait > 0:
await sleep(wait)