|
|
@@ -207,3 +207,44 @@ async def test_oversized_idempotent_response_is_failed_not_left_reserved(
|
|
|
)
|
|
|
== "failed"
|
|
|
)
|
|
|
+
|
|
|
+
|
|
|
+@pytest.mark.asyncio
|
|
|
+async def test_idempotency_key_is_scoped_by_principal_and_route(
|
|
|
+ database: tuple[AsyncEngine, async_sessionmaker[AsyncSession]],
|
|
|
+) -> None:
|
|
|
+ _, sessions = database
|
|
|
+ journal = HttpCommandJournal(sessions)
|
|
|
+ calls: list[str] = []
|
|
|
+
|
|
|
+ async def execute(label: str) -> tuple[int, dict[str, Any]]:
|
|
|
+ calls.append(label)
|
|
|
+ return 200, {"label": label}
|
|
|
+
|
|
|
+ common = {
|
|
|
+ "idempotency_key": "same-key",
|
|
|
+ "request_payload": {"script_build_id": 7},
|
|
|
+ }
|
|
|
+ first = await journal.execute(
|
|
|
+ principal=Principal("subject", "tenant-a"),
|
|
|
+ route_family="script-build:phase-three-advance",
|
|
|
+ command=lambda: execute("advance-a"),
|
|
|
+ **common,
|
|
|
+ )
|
|
|
+ second = await journal.execute(
|
|
|
+ principal=Principal("subject", "tenant-b"),
|
|
|
+ route_family="script-build:phase-three-advance",
|
|
|
+ command=lambda: execute("advance-b"),
|
|
|
+ **common,
|
|
|
+ )
|
|
|
+ third = await journal.execute(
|
|
|
+ principal=Principal("subject", "tenant-a"),
|
|
|
+ route_family="script-build:finalize",
|
|
|
+ command=lambda: execute("finalize-a"),
|
|
|
+ **common,
|
|
|
+ )
|
|
|
+
|
|
|
+ assert first[1]["label"] == "advance-a"
|
|
|
+ assert second[1]["label"] == "advance-b"
|
|
|
+ assert third[1]["label"] == "finalize-a"
|
|
|
+ assert calls == ["advance-a", "advance-b", "finalize-a"]
|