# Poll once a minute without duplicates
Keep a since timestamp watermark, follow each page's next with cursor, and poll again after 60 seconds. Persist processed item ids and make processing idempotent so replaying the timestamp boundary cannot deliver an item twice.
LAST_HELD_AT=${LAST_HELD_AT:-$(date -u +%Y-%m-%dT%H:%M:%SZ)}
while :; do
curl --get "https://api.aurith.ca/v1/items" \
--data-urlencode "since=$LAST_HELD_AT" \
--data-urlencode "limit=50" \
-H "Authorization: Bearer $AURITH_KEY"
# Follow next as cursor until null; persist handled ids and the since watermark.
sleep 60
donelet state = await loadPollState() || {
since: new Date().toISOString(), seen: []
};
while (true) {
const boundary = new Set(state.seen);
let latest = state.since;
let cursor;
do {
const q = new URLSearchParams({ since: state.since, limit: "50" });
if (cursor) q.set("cursor", cursor);
const r = await fetch(`https://api.aurith.ca/v1/items?${q}`, {
headers: { Authorization: `Bearer ${process.env.AURITH_KEY}` }
});
if (!r.ok) throw new Error(`${r.status}: ${await r.text()}`);
const page = await r.json();
for (const item of page.items) {
await handleOnce(item.id, item); // Durable/idempotent by item id.
if (item.held_at > latest) { latest = item.held_at; boundary.clear(); }
if (item.held_at === latest) boundary.add(item.id);
}
cursor = page.next;
} while (cursor);
state = { since: latest, seen: [...boundary] };
await savePollState(state); // Only advance after every page succeeds.
await new Promise(resolve => setTimeout(resolve, 60_000));
}import json, os, time, urllib.parse, urllib.request
state = load_poll_state() or {"since": utc_now(), "seen": []}
while True:
boundary, latest, cursor = set(state["seen"]), state["since"], None
while True:
params = {"since": state["since"], "limit": 50}
if cursor:
params["cursor"] = cursor
url = "https://api.aurith.ca/v1/items?" + urllib.parse.urlencode(params)
req = urllib.request.Request(url, headers={
"Authorization": "Bearer " + os.environ["AURITH_KEY"]})
with urllib.request.urlopen(req) as response:
page = json.load(response)
for item in page["items"]:
handle_once(item["id"], item) # Durable/idempotent by item id.
if item["held_at"] > latest:
latest, boundary = item["held_at"], set()
if item["held_at"] == latest:
boundary.add(item["id"])
cursor = page["next"]
if cursor is None:
break
state = {"since": latest, "seen": list(boundary)}
save_poll_state(state) # Only advance after every page succeeds.
time.sleep(60)