Commit Graph

5 Commits

Author SHA1 Message Date
bcf1f5511c fix: _proxy_string emits no stray colons for a portless proxy
a portless proxy url produced host::user:pass / host: (extra colons), breaking the identity match against the provider pool. the port colon is now omitted when there is no port, mirroring aioproxies' canonical key.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-28 17:18:28 -04:00
aec0a5cc2b fix: remove dead clock param; pin commons v0.2.1 (v0.1.2)
the clock= constructor param was stored (self._clock) but never read — the 429
retry_after wait uses asyncio.sleep directly. it was dead code, and the CLAUDE.md
wrongly claimed it made 429 timing test-controllable. remove the param + the unused
time import, and correct the doc (tests patch commons.retry's sleep + sender.asyncio
.sleep, not a clock seam). bump the commons pin to v0.2.1 (retry attempts floor).

verified: clock param gone, constructs fine, 18/18 fix harness intact.
Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-28 16:16:13 -04:00
40f8cc5b5f fix: never-raises contract + retry migration to commons.aretry (v0.1.1)
- seam bug: _burn/get() only caught ProxiesExhaustedError, but aioproxies.burn()
  raises ValueError ('proxy not in pool') which escaped send() and broke the
  'never raises on send failure' contract. catch ANY exception across the
  duck-typed provider seam and convert to a failed WebhookResult.
- 5xx hot loop: 5xx retries had no backoff (immediate retry, hammering the
  endpoint). migrate 429/5xx retry onto commons.aretry (>=0.2.0) for correct
  exponential backoff + cap.
- lost response: exhausted retries returned a synthetic status-0 result; now the
  real last 4xx/5xx status + body is returned (aretry re-raises the carried
  _Retryable, the loop unwraps it).

verified by execution: burn/get ValueError no longer escapes, 5xx backs off
(~1.9s over 3 retries vs ~0s hot loop), exhausted 5xx returns real 503 + body,
429 retry_after honored, 4xx/rotation/round-robin intact.

Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-27 21:43:41 -04:00
7a0c8abf30 add package: pyproject + src (core Webhook, WebhookResult, errors, discord layer)
Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 14:50:05 -04:00
3f164abf84 init: async webhook sender (aiohttp) with retry & proxy rotation, optional discord embeds
Signed-off-by: disqualifier <dev@disqualifier.me>
2026-06-25 14:50:05 -04:00