from collections import Counter
from local_server import serve
from dataloader_rs import HttpDataset, PyDataloader
TOKEN = "Bearer example-token"
hits = Counter()
def answer(path: str, headers) -> tuple[int, bytes]:
if headers.get("Authorization") != TOKEN:
return 401, b"missing token"
parts = path.split("/")
if len(parts) != 5 or parts[1] != "shards" or parts[3] != "items":
return 404, b"not found"
shard, item = parts[2], parts[4].removesuffix(".txt")
hits[item] += 1
if item == "5" and hits[item] <= 2:
return 503, b"busy, try again"
return 200, f"item {item} of shard {shard}".encode()
def main() -> None:
with serve(answer) as base:
dataset = HttpDataset.from_template(
base + "/shards/{shard}/items/{id}.txt",
{"shard": ["shard a"] * 4 + ["shard b"] * 4, "id": list(range(8))},
headers={"Authorization": TOKEN},
timeout=5.0, retries=3, backoff=0.01, )
loader = PyDataloader(
dataset,
batch_size=4,
num_workers=2,
item_concurrency=4, transform=lambda index, body: body.decode(), )
for batch in loader:
print(batch)
print(f"item 5 took {hits['5']} requests: two 503 answers, then a success")
urls = [base + "/no/such/item", base + "/shards/c/items/0.txt"]
dataset = HttpDataset(urls, headers={"Authorization": TOKEN})
iterator = iter(PyDataloader(dataset, batch_size=1))
for url in urls:
try:
print(f"{url}: {len(next(iterator)[0])} bytes")
except OSError as error:
print(f"{url}: {type(error).__name__}: {error}")
if __name__ == "__main__":
main()