from concurrent.futures import ThreadPoolExecutor from tamq.broker import BrokerIdentity, InputBroker from tamq.store import Store def test_window_counters_survive_reopen_and_isolate_repositories(tmp_path, monkeypatch): monkeypatch.setattr("tamq.broker.validate_targets", lambda targets: None) path = tmp_path / "queue.sqlite3" store = Store(path) left = InputBroker(store, BrokerIdentity("session-1", "left"), limits=(1, 10, 10)) right = InputBroker(store, BrokerIdentity("session-1", "right"), limits=(1, 10, 10)) assert left.inspect_operator_line("To:target: left") is not None assert right.inspect_operator_line("To:target: right") is not None store.close() reopened = Store(path) assert reopened.line_state("session-1", "left")["messages"] == 1 assert reopened.line_state("session-1", "right")["messages"] == 1 blocked = [] left = InputBroker( reopened, BrokerIdentity("session-1", "left"), limits=(1, 10, 10), notify=blocked.append, ) assert left.inspect_worker_line("To:target: blocked") is None assert left.inspect_worker_line("") is None assert "lines of messages" in blocked[-1] def test_atomic_message_admission_does_not_cross_limit(tmp_path, monkeypatch): monkeypatch.setattr("tamq.broker.validate_targets", lambda targets: None) path = tmp_path / "queue.sqlite3" seed = Store(path) seed.configure_window("session-1", "source", (1, 100, 100)) seed.close() def send(body): store = Store(path) try: broker = InputBroker( store, BrokerIdentity("session-1", "source"), limits=(1, 100, 100), ) broker.inspect_worker_line(f"To:target: {body}") return broker.inspect_worker_line("") is not None finally: store.close() with ThreadPoolExecutor(max_workers=2) as executor: accepted = list(executor.map(send, ("one", "two"))) assert sorted(accepted) == [False, True] final = Store(path) assert len(final.list()) == 1 assert final.line_state("session-1", "source")["messages"] == 1 def test_new_session_generation_starts_a_fresh_ledger(tmp_path, monkeypatch): monkeypatch.setattr("tamq.broker.validate_targets", lambda targets: None) store = Store(tmp_path / "queue.sqlite3") first = InputBroker(store, BrokerIdentity("generation-1", "source"), limits=(1, 10, 10)) second = InputBroker(store, BrokerIdentity("generation-2", "source"), limits=(1, 10, 10)) assert first.inspect_operator_line("To:target: first") is not None assert second.inspect_operator_line("To:target: second") is not None assert len(store.list()) == 2