"""Integration: the bot's DURABLE, idempotent result intake (/conjurer). The expensive-result guarantees on the bot side: * every result is persisted to the inbox before it is acked, * a resend of a not-yet-delivered result is dropped (no double render), * once rendered (mark_delivered) further resends are dropped and it leaves the inbox, * on startup, an accepted-but-unrendered result is replayed from the inbox, * health-check pongs are never persisted. """ import pytest import communication_subroutine as cs from durable_queue import DiskQueue @pytest.fixture def spool(tmp_path, monkeypatch): inbox = DiskQueue(str(tmp_path / "inbox")) delivered = DiskQueue(str(tmp_path / "delivered")) monkeypatch.setattr(cs, "_inbox", inbox) monkeypatch.setattr(cs, "_delivered", delivered) cs.API_KEY = None while not cs.incoming_q.empty(): cs.incoming_q.get() return inbox, delivered def _drain_incoming(): out = [] while not cs.incoming_q.empty(): out.append(cs.incoming_q.get()) return out def _payload(uuid): return {uuid: {"10.1000/xyz": {"Title": ["A Real Paper"], "type": "journal-article"}}} def test_result_is_persisted_then_queued(spool): inbox, _delivered = spool resp = cs.app.test_client().post("/conjurer", json=_payload("u1")) assert resp.status_code == 200 assert inbox.contains("u1") # durable before ack assert _drain_incoming() == [_payload("u1")] def test_resend_while_pending_is_not_requeued(spool): client = cs.app.test_client() client.post("/conjurer", json=_payload("u2")) _drain_incoming() # consume the first queueing # Resend before it was rendered: inbox still holds it -> dropped, not doubled. client.post("/conjurer", json=_payload("u2")) assert _drain_incoming() == [] def test_resend_after_delivery_is_dropped(spool): inbox, delivered = spool client = cs.app.test_client() client.post("/conjurer", json=_payload("u3")) _drain_incoming() cs.mark_delivered("u3") assert not inbox.contains("u3") assert delivered.contains("u3") # A late resend of an already-delivered result must not re-render. client.post("/conjurer", json=_payload("u3")) assert _drain_incoming() == [] def test_replay_requeues_only_undelivered(spool): inbox, delivered = spool inbox.put("u4", _payload("u4")) inbox.put("u5", _payload("u5")) delivered.put("u5", {}) # u5 already shown to the user cs.replay_inbox() keys = [list(p.keys())[0] for p in _drain_incoming()] assert keys == ["u4"] # only the un-rendered one replayed assert not inbox.contains("u5") # the delivered one is cleaned from the inbox def test_empty_result_still_persisted_and_delivered(spool): inbox, _delivered = spool cs.app.test_client().post("/conjurer", json={"u6": {}}) assert inbox.contains("u6") assert _drain_incoming() == [{"u6": {}}] def test_pong_is_not_persisted(spool): inbox, _delivered = spool cs.app.test_client().post("/conjurer", json={"__pong__": "ping-1"}) assert len(inbox) == 0 assert _drain_incoming() == [{"__pong__": "ping-1"}]