Batch-committing the in-flight app work (all modules compile clean): - app/payments.py, app/packs.py, app/discogs_mp.py, app/dealgod.py (new) - admin_routes, main, navigator/sales/shop routes, site/search.html - customer_woo_sync + disc_sync tweaks; test_dealgod_supply, test_startup_ddl Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
69 lines
2.0 KiB
Python
69 lines
2.0 KiB
Python
"""Self-check for the concurrent dealgod.supply() batcher. No network — fake httpx client.
|
|
Run: .venv/bin/python test_dealgod_supply.py"""
|
|
import asyncio
|
|
import app.dealgod as dg
|
|
|
|
SEEN = [] # batches the fake client received
|
|
|
|
|
|
class _Resp:
|
|
status_code = 200
|
|
|
|
def __init__(self, ids):
|
|
self.ids = ids
|
|
|
|
def json(self):
|
|
return {"results": {str(i): {"n": 1} for i in self.ids}}
|
|
|
|
|
|
class _FakeClient:
|
|
def __init__(self, *a, **k):
|
|
pass
|
|
|
|
async def __aenter__(self):
|
|
return self
|
|
|
|
async def __aexit__(self, *a):
|
|
return False
|
|
|
|
async def post(self, url, json=None):
|
|
ids = json["ids"]
|
|
SEEN.append(list(ids))
|
|
if -1 in ids: # poison sentinel → simulate a failing batch
|
|
raise RuntimeError("simulated batch failure")
|
|
return _Resp(ids)
|
|
|
|
|
|
async def _fake_key(db):
|
|
return "fake-key"
|
|
|
|
|
|
def test_supply():
|
|
orig_client, orig_key = dg.httpx.AsyncClient, dg._key
|
|
dg.httpx.AsyncClient, dg._key = _FakeClient, _fake_key
|
|
try:
|
|
# 450 ids → 3 batches (200/200/50), all results merged
|
|
SEEN.clear()
|
|
res = asyncio.run(dg.supply(None, list(range(450))))
|
|
assert len(SEEN) == 3, SEEN
|
|
assert sorted(len(b) for b in SEEN) == [50, 200, 200]
|
|
assert len(res) == 450 and res["0"] == {"n": 1} and res["449"] == {"n": 1}
|
|
|
|
# empty ids → {} with zero calls
|
|
SEEN.clear()
|
|
assert asyncio.run(dg.supply(None, [])) == {} and SEEN == []
|
|
|
|
# ONE failing batch among several is dropped; the others still merge (isolation)
|
|
SEEN.clear()
|
|
ids2 = list(range(200)) + [-1] + list(range(201, 250)) # batch 2 holds the poison
|
|
res2 = asyncio.run(dg.supply(None, ids2))
|
|
assert len(SEEN) == 2
|
|
assert len(res2) == 200 and "0" in res2 and "201" not in res2
|
|
print("ok — concurrent batching, merge, empty-guard, degrade-isolation all pass")
|
|
finally:
|
|
dg.httpx.AsyncClient, dg._key = orig_client, orig_key
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_supply()
|