Cvičení 12 · MortgageAccountOpeningRequested → MortgageAccountOpened, Inbox
Mortgage Account: duplicity a idempotence
- at-least-once
- duplicity
- idempotence
- Inbox
Princip
Broker garantuje „aspoň jednou“, ne „právě jednou“. Stejná zpráva může dorazit dvakrát (ztracené potvrzení, redelivery, retry).
Bez idempotence služba otevře druhý účet. Idempotentní příjemce si pamatuje zpracovaná eventId (Inbox) a pro stejnou žádost nevytvoří nový účinek, ale vrátí původní výsledek.
Inbox se zapisuje ve stejné transakci jako účinek, jinak se opět otevře okno pro duplicitu.
Co sledovat
- Počet účtů v lokální databázi služby.
- Stopa „duplicate-ignored“ v timeline brokeru.
Bez řešení / S řešením
Bez řešení
Spustit s duplicitním doručením
Broker doručí každý požadavek na otevření účtu 2×. Služba nemá Inbox.
Spustit v simulátoru bez řešeníS řešením
Spustit s Inboxem
Služba druhé doručení pozná podle eventId a ignoruje ho. Vznikne jediný účet.
Spustit v simulátoru s řešenímCo udělat: Klikni na „Spustit s duplicitním doručením“. Na co se dívat: Mortgage Account otevře dva účty pro jednu hypotéku. Simulátor potřebuje JavaScript a běží jako samostatná aplikace.
Zkus to ve svém projektu
Zkopíruj prompt do svého coding agenta (Claude Code, Copilot, Codex…) a spusť ho v repozitáři svého projektu.
Udělat konzumenta MortgageAccountOpeningRequested idempotentním přes Inbox tabulku v téže transakci jako účinek.
# Úkol pro coding agenta: Mortgage Account: duplicity a idempotence Stack: Java. Režim: s vedením. Cíl: Udělat konzumenta MortgageAccountOpeningRequested idempotentním přes Inbox tabulku v téže transakci jako účinek. ## Kontext existujícího kódu Pracuješ v existujícím projektu (Java backend (typicky Java 21, Spring Boot, JPA nebo JDBC). Použij build nástroj a styl, který projekt už má (Maven/Gradle, JUnit 5).). Doména: hypoteční kalkulačka, která se postupně mění v event-driven systém (kalkulačka, rizika, schvalování, identita, účet, dokumenty, výplata). Předpoklad: projekt má broker a zprávu `MortgageAccountOpeningRequested` (`applicationId`, `identityCheckId`) od Customer Identity po ověření totožnosti. Pokud ne, nejdřív založ minimálního producenta a konzumenta. Nejdřív čti, nic neměň. Najdi a stručně shrň: - Handler, který otevírá účet, a transakční hranici. - Zda už existuje inbox/deduplikace v messaging knihovně (např. inbox v MassTransit/Wolverine). - Přirozený obchodní klíč (applicationId). - Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (broker klient, outbox, retry), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. ## Očekávané chování Broker doručuje „aspoň jednou“: stejná zpráva může dorazit dvakrát a bez idempotence vznikne druhý účet. Idempotentní příjemce zapíše `eventId` do Inboxu v téže transakci jako účet a druhé doručení ignoruje. Příklad: duplicita dostane původní účet (úspěch, ne 409) a odpověď `MortgageAccountOpened` se stejným `eventId`. ## Konkrétní úkol Technická specifika (Java): `@Transactional` handler, unikátní index na `message_id` a `application_id`. Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení: 1. Plán: kde je klíč deduplikace (eventId) a kde obchodní klíč (applicationId). 2. Tabulka Inbox (messageId unikátní) v databázi služby účtu, zapisovaná ve stejné transakci jako vytvoření účtu. Po síti posílej `eventId` jako idempotency key. 3. Duplicita vrací původní výsledek a znovu publikuje odpovědní událost (příklad výše). 4. Unikátní omezení na obchodní klíč jako druhá vrstva obrany. Nesnese-li ho stávající tabulka, dej ho do nové tabulky ve stejné transakci. 5. Test: stejná zpráva 2× → jeden účet; dva různé požadavky na stejnou žádost → jeden účet; souběh, který bez unikátního klíče selže (dvě spojení k databázi, nebo dvojník se starým čtením). Na co si dát pozor: - Deduplikace „if exists“ bez unikátního omezení má závod. - Inbox roste: plán čištění po retenci; ta musí přečkat retry, DLQ i ruční redrive. ## Co nesmíš měnit - Stávající veřejné API a chování endpointů kalkulačky, které teď funguje. - Databázové schéma stávajících tabulek (nové tabulky/migrace jsou v pořádku, přejmenování a mazání ne). - Cizí testy, seed data a existující hodnoty. Když je změna nutná, dej ji do samostatného commitu a uveď ji. Pokud změna tvaru události nebo nový konzument nutně mění existující test, uprav ho v samostatném commitu a v závěru uveď proč. - Veřejné kontrakty (API, schémata událostí) bez zpětné kompatibility. ## Hotovo, když - Test duplicity i souběžného doručení. - Inbox a účinek jsou v jedné transakci (test: selhání zápisu do inboxu nenechá účet). - Existující knihovna použita, pokud je k dispozici. - JUnit 5 testy ve stávající struktuře `src/test/java` projdou build nástrojem projektu. - V závěru uveď: co jsi změnil, co jsi předpokládal, co zbývá.
# Úkol pro coding agenta: Mortgage Account: duplicity a idempotence Stack: Java. Režim: challenge. Cíl: Udělat konzumenta MortgageAccountOpeningRequested idempotentním přes Inbox tabulku v téže transakci jako účinek. ## Kontext existujícího kódu Pracuješ v existujícím projektu (Java backend (typicky Java 21, Spring Boot, JPA nebo JDBC). Použij build nástroj a styl, který projekt už má (Maven/Gradle, JUnit 5).). Doména: hypoteční kalkulačka, která se postupně mění v event-driven systém (kalkulačka, rizika, schvalování, identita, účet, dokumenty, výplata). Předpoklad: projekt má broker a zprávu `MortgageAccountOpeningRequested` (`applicationId`, `identityCheckId`) od Customer Identity po ověření totožnosti. Pokud ne, nejdřív založ minimálního producenta a konzumenta. Nejdřív čti, nic neměň. Najdi a stručně shrň: - Handler, který otevírá účet, a transakční hranici. - Zda už existuje inbox/deduplikace v messaging knihovně (např. inbox v MassTransit/Wolverine). - Přirozený obchodní klíč (applicationId). - Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (broker klient, outbox, retry), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. ## Očekávané chování Broker doručuje „aspoň jednou“: stejná zpráva může dorazit dvakrát a bez idempotence vznikne druhý účet. Idempotentní příjemce zapíše `eventId` do Inboxu v téže transakci jako účet a druhé doručení ignoruje. Příklad: duplicita dostane původní účet (úspěch, ne 409) a odpověď `MortgageAccountOpened` se stejným `eventId`. ## Zadání (Challenge) Zaruč, že opakované doručení MortgageAccountOpeningRequested nikdy nevytvoří druhý účet, ani při souběžném doručení. Technická specifika (Java): `@Transactional` handler, unikátní index na `message_id` a `application_id`. Postup si zvol sám. Pasti v tomto tématu nejsou vypsané: najdi je (souběh, opakované doručení, pořadí, selhání uprostřed) a ke každé napiš test, který by ji odhalil. Na konci vypiš, jaké pasti jsi našel a které jsi vědomě nechal otevřené. ## Co nesmíš měnit - Stávající veřejné API a chování endpointů kalkulačky, které teď funguje. - Databázové schéma stávajících tabulek (nové tabulky/migrace jsou v pořádku, přejmenování a mazání ne). - Cizí testy, seed data a existující hodnoty. Když je změna nutná, dej ji do samostatného commitu a uveď ji. Pokud změna tvaru události nebo nový konzument nutně mění existující test, uprav ho v samostatném commitu a v závěru uveď proč. - Veřejné kontrakty (API, schémata událostí) bez zpětné kompatibility. ## Hotovo, když - Test duplicity i souběžného doručení. - Inbox a účinek jsou v jedné transakci (test: selhání zápisu do inboxu nenechá účet). - Existující knihovna použita, pokud je k dispozici. - JUnit 5 testy ve stávající struktuře `src/test/java` projdou build nástrojem projektu. - V závěru uveď: co jsi změnil, co jsi předpokládal, co zbývá.
# Úkol pro coding agenta: Mortgage Account: duplicity a idempotence Stack: C#. Režim: s vedením. Cíl: Udělat konzumenta MortgageAccountOpeningRequested idempotentním přes Inbox tabulku v téže transakci jako účinek. ## Kontext existujícího kódu Pracuješ v existujícím projektu (C# backend (.NET, ASP.NET Core, EF Core nebo Dapper). Použij solution, styl a DI konvence, které projekt už má (xUnit/NUnit).). Doména: hypoteční kalkulačka, která se postupně mění v event-driven systém (kalkulačka, rizika, schvalování, identita, účet, dokumenty, výplata). Předpoklad: projekt má broker a zprávu `MortgageAccountOpeningRequested` (`applicationId`, `identityCheckId`) od Customer Identity po ověření totožnosti. Pokud ne, nejdřív založ minimálního producenta a konzumenta. Nejdřív čti, nic neměň. Najdi a stručně shrň: - Handler, který otevírá účet, a transakční hranici. - Zda už existuje inbox/deduplikace v messaging knihovně (např. inbox v MassTransit/Wolverine). - Přirozený obchodní klíč (applicationId). - Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (broker klient, outbox, retry), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. ## Očekávané chování Broker doručuje „aspoň jednou“: stejná zpráva může dorazit dvakrát a bez idempotence vznikne druhý účet. Idempotentní příjemce zapíše `eventId` do Inboxu v téže transakci jako účet a druhé doručení ignoruje. Příklad: duplicita dostane původní účet (úspěch, ne 409) a odpověď `MortgageAccountOpened` se stejným `eventId`. ## Konkrétní úkol Technická specifika (C#): Transakce `DbContext`, unikátní indexy; použij inbox existující messaging knihovny, pokud ho má. Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení: 1. Plán: kde je klíč deduplikace (eventId) a kde obchodní klíč (applicationId). 2. Tabulka Inbox (messageId unikátní) v databázi služby účtu, zapisovaná ve stejné transakci jako vytvoření účtu. Po síti posílej `eventId` jako idempotency key. 3. Duplicita vrací původní výsledek a znovu publikuje odpovědní událost (příklad výše). 4. Unikátní omezení na obchodní klíč jako druhá vrstva obrany. Nesnese-li ho stávající tabulka, dej ho do nové tabulky ve stejné transakci. 5. Test: stejná zpráva 2× → jeden účet; dva různé požadavky na stejnou žádost → jeden účet; souběh, který bez unikátního klíče selže (dvě spojení k databázi, nebo dvojník se starým čtením). Na co si dát pozor: - Deduplikace „if exists“ bez unikátního omezení má závod. - Inbox roste: plán čištění po retenci; ta musí přečkat retry, DLQ i ruční redrive. ## Co nesmíš měnit - Stávající veřejné API a chování endpointů kalkulačky, které teď funguje. - Databázové schéma stávajících tabulek (nové tabulky/migrace jsou v pořádku, přejmenování a mazání ne). - Cizí testy, seed data a existující hodnoty. Když je změna nutná, dej ji do samostatného commitu a uveď ji. Pokud změna tvaru události nebo nový konzument nutně mění existující test, uprav ho v samostatném commitu a v závěru uveď proč. - Veřejné kontrakty (API, schémata událostí) bez zpětné kompatibility. ## Hotovo, když - Test duplicity i souběžného doručení. - Inbox a účinek jsou v jedné transakci (test: selhání zápisu do inboxu nenechá účet). - Existující knihovna použita, pokud je k dispozici. - Testy ve stávajícím testovacím projektu projdou (`dotnet test`). - V závěru uveď: co jsi změnil, co jsi předpokládal, co zbývá.
# Úkol pro coding agenta: Mortgage Account: duplicity a idempotence Stack: C#. Režim: challenge. Cíl: Udělat konzumenta MortgageAccountOpeningRequested idempotentním přes Inbox tabulku v téže transakci jako účinek. ## Kontext existujícího kódu Pracuješ v existujícím projektu (C# backend (.NET, ASP.NET Core, EF Core nebo Dapper). Použij solution, styl a DI konvence, které projekt už má (xUnit/NUnit).). Doména: hypoteční kalkulačka, která se postupně mění v event-driven systém (kalkulačka, rizika, schvalování, identita, účet, dokumenty, výplata). Předpoklad: projekt má broker a zprávu `MortgageAccountOpeningRequested` (`applicationId`, `identityCheckId`) od Customer Identity po ověření totožnosti. Pokud ne, nejdřív založ minimálního producenta a konzumenta. Nejdřív čti, nic neměň. Najdi a stručně shrň: - Handler, který otevírá účet, a transakční hranici. - Zda už existuje inbox/deduplikace v messaging knihovně (např. inbox v MassTransit/Wolverine). - Přirozený obchodní klíč (applicationId). - Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (broker klient, outbox, retry), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. ## Očekávané chování Broker doručuje „aspoň jednou“: stejná zpráva může dorazit dvakrát a bez idempotence vznikne druhý účet. Idempotentní příjemce zapíše `eventId` do Inboxu v téže transakci jako účet a druhé doručení ignoruje. Příklad: duplicita dostane původní účet (úspěch, ne 409) a odpověď `MortgageAccountOpened` se stejným `eventId`. ## Zadání (Challenge) Zaruč, že opakované doručení MortgageAccountOpeningRequested nikdy nevytvoří druhý účet, ani při souběžném doručení. Technická specifika (C#): Transakce `DbContext`, unikátní indexy; použij inbox existující messaging knihovny, pokud ho má. Postup si zvol sám. Pasti v tomto tématu nejsou vypsané: najdi je (souběh, opakované doručení, pořadí, selhání uprostřed) a ke každé napiš test, který by ji odhalil. Na konci vypiš, jaké pasti jsi našel a které jsi vědomě nechal otevřené. ## Co nesmíš měnit - Stávající veřejné API a chování endpointů kalkulačky, které teď funguje. - Databázové schéma stávajících tabulek (nové tabulky/migrace jsou v pořádku, přejmenování a mazání ne). - Cizí testy, seed data a existující hodnoty. Když je změna nutná, dej ji do samostatného commitu a uveď ji. Pokud změna tvaru události nebo nový konzument nutně mění existující test, uprav ho v samostatném commitu a v závěru uveď proč. - Veřejné kontrakty (API, schémata událostí) bez zpětné kompatibility. ## Hotovo, když - Test duplicity i souběžného doručení. - Inbox a účinek jsou v jedné transakci (test: selhání zápisu do inboxu nenechá účet). - Existující knihovna použita, pokud je k dispozici. - Testy ve stávajícím testovacím projektu projdou (`dotnet test`). - V závěru uveď: co jsi změnil, co jsi předpokládal, co zbývá.
# Úkol pro coding agenta: Mortgage Account: duplicity a idempotence Stack: Web (HTML/JS nebo stack aplikace). Režim: s vedením. Cíl: Udělat konzumenta MortgageAccountOpeningRequested idempotentním přes Inbox tabulku v téže transakci jako účinek. ## Kontext existujícího kódu Pracuješ v existujícím projektu (webová aplikace: frontend v prohlížeči, případně s vlastním backendem. Když má projekt backend, patří event store, broker a služby na backend a body o endpointech a tabulkách se týkají jeho. Když backend nemá, použij IndexedDB v prohlížeči a v testech `fake-indexeddb`. Framework a test runner projektu zachovej; nové závislosti přidávej jen s odůvodněním.). Doména: hypoteční kalkulačka, která se postupně mění v event-driven systém (kalkulačka, rizika, schvalování, identita, účet, dokumenty, výplata). Předpoklad: projekt má broker a zprávu `MortgageAccountOpeningRequested` (`applicationId`, `identityCheckId`) od Customer Identity po ověření totožnosti. Pokud ne, nejdřív založ minimálního producenta a konzumenta. Nejdřív čti, nic neměň. Najdi a stručně shrň: - Handler, který otevírá účet, a transakční hranici. - Zda už existuje inbox/deduplikace v messaging knihovně (např. inbox v MassTransit/Wolverine). - Přirozený obchodní klíč (applicationId). - Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (broker klient, outbox, retry), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. ## Očekávané chování Broker doručuje „aspoň jednou“: stejná zpráva může dorazit dvakrát a bez idempotence vznikne druhý účet. Idempotentní příjemce zapíše `eventId` do Inboxu v téže transakci jako účet a druhé doručení ignoruje. Příklad: duplicita dostane původní účet (úspěch, ne 409) a odpověď `MortgageAccountOpened` se stejným `eventId`. ## Konkrétní úkol Technická specifika (Web (HTML/JS nebo stack aplikace)): S backendem jedna transakce služby účtu přes inbox i účet; bez backendu jedna IndexedDB transakce přes inbox i data. Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení: 1. Plán: kde je klíč deduplikace (eventId) a kde obchodní klíč (applicationId). 2. Tabulka Inbox (messageId unikátní) v databázi služby účtu, zapisovaná ve stejné transakci jako vytvoření účtu. Po síti posílej `eventId` jako idempotency key. 3. Duplicita vrací původní výsledek a znovu publikuje odpovědní událost (příklad výše). 4. Unikátní omezení na obchodní klíč jako druhá vrstva obrany. Nesnese-li ho stávající tabulka, dej ho do nové tabulky ve stejné transakci. 5. Test: stejná zpráva 2× → jeden účet; dva různé požadavky na stejnou žádost → jeden účet; souběh, který bez unikátního klíče selže (dvě spojení k databázi, nebo dvojník se starým čtením). Na co si dát pozor: - Deduplikace „if exists“ bez unikátního omezení má závod. - Inbox roste: plán čištění po retenci; ta musí přečkat retry, DLQ i ruční redrive. ## Co nesmíš měnit - Stávající veřejné API a chování endpointů kalkulačky, které teď funguje. - Databázové schéma stávajících tabulek (nové tabulky/migrace jsou v pořádku, přejmenování a mazání ne). - Cizí testy, seed data a existující hodnoty. Když je změna nutná, dej ji do samostatného commitu a uveď ji. Pokud změna tvaru události nebo nový konzument nutně mění existující test, uprav ho v samostatném commitu a v závěru uveď proč. - Veřejné kontrakty (API, schémata událostí) bez zpětné kompatibility. ## Hotovo, když - Test duplicity i souběžného doručení. - Inbox a účinek jsou v jedné transakci (test: selhání zápisu do inboxu nenechá účet). - Existující knihovna použita, pokud je k dispozici. - Testy projdou stávajícím test runnerem; lint a build projdou, pokud je projekt má. - V závěru uveď: co jsi změnil, co jsi předpokládal, co zbývá.
# Úkol pro coding agenta: Mortgage Account: duplicity a idempotence Stack: Web (HTML/JS nebo stack aplikace). Režim: challenge. Cíl: Udělat konzumenta MortgageAccountOpeningRequested idempotentním přes Inbox tabulku v téže transakci jako účinek. ## Kontext existujícího kódu Pracuješ v existujícím projektu (webová aplikace: frontend v prohlížeči, případně s vlastním backendem. Když má projekt backend, patří event store, broker a služby na backend a body o endpointech a tabulkách se týkají jeho. Když backend nemá, použij IndexedDB v prohlížeči a v testech `fake-indexeddb`. Framework a test runner projektu zachovej; nové závislosti přidávej jen s odůvodněním.). Doména: hypoteční kalkulačka, která se postupně mění v event-driven systém (kalkulačka, rizika, schvalování, identita, účet, dokumenty, výplata). Předpoklad: projekt má broker a zprávu `MortgageAccountOpeningRequested` (`applicationId`, `identityCheckId`) od Customer Identity po ověření totožnosti. Pokud ne, nejdřív založ minimálního producenta a konzumenta. Nejdřív čti, nic neměň. Najdi a stručně shrň: - Handler, který otevírá účet, a transakční hranici. - Zda už existuje inbox/deduplikace v messaging knihovně (např. inbox v MassTransit/Wolverine). - Přirozený obchodní klíč (applicationId). - Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (broker klient, outbox, retry), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. ## Očekávané chování Broker doručuje „aspoň jednou“: stejná zpráva může dorazit dvakrát a bez idempotence vznikne druhý účet. Idempotentní příjemce zapíše `eventId` do Inboxu v téže transakci jako účet a druhé doručení ignoruje. Příklad: duplicita dostane původní účet (úspěch, ne 409) a odpověď `MortgageAccountOpened` se stejným `eventId`. ## Zadání (Challenge) Zaruč, že opakované doručení MortgageAccountOpeningRequested nikdy nevytvoří druhý účet, ani při souběžném doručení. Technická specifika (Web (HTML/JS nebo stack aplikace)): S backendem jedna transakce služby účtu přes inbox i účet; bez backendu jedna IndexedDB transakce přes inbox i data. Postup si zvol sám. Pasti v tomto tématu nejsou vypsané: najdi je (souběh, opakované doručení, pořadí, selhání uprostřed) a ke každé napiš test, který by ji odhalil. Na konci vypiš, jaké pasti jsi našel a které jsi vědomě nechal otevřené. ## Co nesmíš měnit - Stávající veřejné API a chování endpointů kalkulačky, které teď funguje. - Databázové schéma stávajících tabulek (nové tabulky/migrace jsou v pořádku, přejmenování a mazání ne). - Cizí testy, seed data a existující hodnoty. Když je změna nutná, dej ji do samostatného commitu a uveď ji. Pokud změna tvaru události nebo nový konzument nutně mění existující test, uprav ho v samostatném commitu a v závěru uveď proč. - Veřejné kontrakty (API, schémata událostí) bez zpětné kompatibility. ## Hotovo, když - Test duplicity i souběžného doručení. - Inbox a účinek jsou v jedné transakci (test: selhání zápisu do inboxu nenechá účet). - Existující knihovna použita, pokud je k dispozici. - Testy projdou stávajícím test runnerem; lint a build projdou, pokud je projekt má. - V závěru uveď: co jsi změnil, co jsi předpokládal, co zbývá.
Související části prezentace
Školení pro váš tým
Chcete školení pro svůj tým?
Školení vedeme na vašem kódu a vašem doménovém problému. Domluvíme rozsah, termín a formu.
Probrat školení