Cvičení 15 · Zápis a publikace nejsou jedna transakce (dual write)

Transactional Outbox

  • dual write
  • Outbox
  • relay
  • Inbox + Outbox

Princip

Služba zapíše událost do event store a pak ji publikuje do brokeru. To jsou dvě operace nad dvěma systémy, nejde je udělat atomicky. Mezi nimi může služba spadnout nebo broker selhat.

Výsledek: událost je uložená, ale nikdo se o ní nedozví a proces stojí.

Transactional Outbox: událost a záznam „k odeslání“ se zapíšou v jedné transakci. Samostatný relay je pak doručí do brokeru a opakuje, dokud se to nepovede. Spolu s Inboxem u příjemce vzniká efektivně „právě jednou“.

Co sledovat

  • Efekt „publikace selhala“ a stav „proces visí“.
  • S Outboxem: řádky čekající na relay a jejich pokusy.
  • Tlačítko „Přestavět projekci“ ukazuje, že event store pravdu měl.

Bez řešení / S řešením

Bez řešení

Spustit s 70% ztrátou publikace

Publikace do brokeru selhává (70 %). Události se zapisují do event store, ale část z nich se nikdy nedoručí.

Spustit v simulátoru bez řešení

S řešením

Spustit s Outboxem

Relay posílá události z outbox tabulky, dokud neuspěje. Proces zaostává, ale neztratí se nic.

Spustit v simulátoru s řešením

Co udělat: Klikni na „Spustit s 70% ztrátou publikace“. Na co se dívat: Událost je uložená, ale proces se nikdy nedokončí. 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.

Nahradit přímou publikaci po zápisu transakčním Outboxem s relay procesem.

Jazyk
Varianta
# Úkol pro coding agenta: Transactional Outbox

Stack: Java. Režim: s vedením.
Cíl: Nahradit přímou publikaci po zápisu transakčním Outboxem s relay procesem.

## 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 producenty, kteří po zápisu publikují. Pokud ne, nejdřív založ minimálního producenta: zápis stavu a `publish` do brokeru v paměti.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Všechna místa, kde se po `save` volá `publish`/`send` (dual write), i v konzumentech, a kde je u každého zápis stavu (stejná databáze, jiná služba, žádný).
- Zda broker knihovna projektu už Outbox nabízí (event store s relayem z feedu už outboxem je).
- Transakční hranici (jedna DB transakce).
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (outbox, relay), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. Když chybí, navrhni ji v plánu.

## Očekávané chování

Zápis stavu a publikace jsou dvě operace nad dvěma systémy: spadne-li mezi nimi služba nebo broker, stav je uložený, ale nikdo se o něm nedozví a proces stojí. Outbox zapíše řádek „k odeslání“ v téže transakci jako stav a relay ho doručuje, dokud neuspěje. Doručuje „aspoň jednou“, s Inboxem u příjemce vzniká efektivně „právě jednou“. Příklad: broker odmítá 70 % publikací; proces zaostává, ale neztratí se nic.

## Konkrétní úkol

Technická specifika (Java): `@Transactional` zápis, relay jako `@Scheduled` nebo Debezium CDC, pokud je v organizaci.

Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení:
1. Plán: schéma tabulky outbox (id, type, topic, payload, headers, aggregate_key, position, created_at, sent_at, attempts, next_attempt_at, locked_until) a kde žije, když je stav v jiné službě.
2. Zápis stavu a outbox řádku v jedné transakci; producent bez vlastního zápisu zapíše jen řádek outboxu.
3. Relay (background worker) po zápisu a na časovač: načte neodeslané, odešle v pořadí, označí; selhání = `attempts + 1` a další pokus po backoffu.
4. Odběratelé jsou idempotentní (Inbox, unikátní obchodní klíč, idempotency key), relay doručuje „aspoň jednou“; kde to neplatí, uveď v závěru.
5. Test přes broker s poruchou: (a) broker neběží → po obnově všechny zprávy v pořadí; (b) výpadek mezi zápisem a publikací; (c) ztracené potvrzení → duplicita, efekt jednou. Kontrola: bez outboxu (b) padá.

Na co si dát pozor:
- Více instancí relay: `SKIP LOCKED` jen nad prvním neodeslaným řádkem agregátu a zámek s lease, jinak druhá instance předběhne první; nebo jedna instance.
- Zpráva, kterou broker trvale odmítá, zablokuje svůj agregát: alarm na stáří outboxu.

## 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 výpadku brokeru (a) až (c) a kontrola bez outboxu.
- Zápis stavu a outboxu je atomický (test s chybou uvnitř transakce).
- Relay ve více instancích bez dvojí publikace a s pořadím v agregátu (test), nebo zdokumentovaná jedna instance.
- 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: Transactional Outbox

Stack: Java. Režim: challenge.
Cíl: Nahradit přímou publikaci po zápisu transakčním Outboxem s relay procesem.

## 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 producenty, kteří po zápisu publikují. Pokud ne, nejdřív založ minimálního producenta: zápis stavu a `publish` do brokeru v paměti.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Všechna místa, kde se po `save` volá `publish`/`send` (dual write), i v konzumentech, a kde je u každého zápis stavu (stejná databáze, jiná služba, žádný).
- Zda broker knihovna projektu už Outbox nabízí (event store s relayem z feedu už outboxem je).
- Transakční hranici (jedna DB transakce).
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (outbox, relay), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. Když chybí, navrhni ji v plánu.

## Očekávané chování

Zápis stavu a publikace jsou dvě operace nad dvěma systémy: spadne-li mezi nimi služba nebo broker, stav je uložený, ale nikdo se o něm nedozví a proces stojí. Outbox zapíše řádek „k odeslání“ v téže transakci jako stav a relay ho doručuje, dokud neuspěje. Doručuje „aspoň jednou“, s Inboxem u příjemce vzniká efektivně „právě jednou“. Příklad: broker odmítá 70 % publikací; proces zaostává, ale neztratí se nic.

## Zadání (Challenge)

Zaruč, že každá uložená událost bude dříve nebo později publikována, i když broker nebo služba mezitím selžou.

Technická specifika (Java): `@Transactional` zápis, relay jako `@Scheduled` nebo Debezium CDC, pokud je v organizaci.

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 výpadku brokeru (a) až (c) a kontrola bez outboxu.
- Zápis stavu a outboxu je atomický (test s chybou uvnitř transakce).
- Relay ve více instancích bez dvojí publikace a s pořadím v agregátu (test), nebo zdokumentovaná jedna instance.
- 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: Transactional Outbox

Stack: C#. Režim: s vedením.
Cíl: Nahradit přímou publikaci po zápisu transakčním Outboxem s relay procesem.

## 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 producenty, kteří po zápisu publikují. Pokud ne, nejdřív založ minimálního producenta: zápis stavu a `publish` do brokeru v paměti.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Všechna místa, kde se po `save` volá `publish`/`send` (dual write), i v konzumentech, a kde je u každého zápis stavu (stejná databáze, jiná služba, žádný).
- Zda broker knihovna projektu už Outbox nabízí (event store s relayem z feedu už outboxem je).
- Transakční hranici (jedna DB transakce).
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (outbox, relay), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. Když chybí, navrhni ji v plánu.

## Očekávané chování

Zápis stavu a publikace jsou dvě operace nad dvěma systémy: spadne-li mezi nimi služba nebo broker, stav je uložený, ale nikdo se o něm nedozví a proces stojí. Outbox zapíše řádek „k odeslání“ v téže transakci jako stav a relay ho doručuje, dokud neuspěje. Doručuje „aspoň jednou“, s Inboxem u příjemce vzniká efektivně „právě jednou“. Příklad: broker odmítá 70 % publikací; proces zaostává, ale neztratí se nic.

## Konkrétní úkol

Technická specifika (C#): Transakce `DbContext`, relay jako `BackgroundService`; nejdřív zkontroluj outbox v messaging knihovně projektu.

Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení:
1. Plán: schéma tabulky outbox (id, type, topic, payload, headers, aggregate_key, position, created_at, sent_at, attempts, next_attempt_at, locked_until) a kde žije, když je stav v jiné službě.
2. Zápis stavu a outbox řádku v jedné transakci; producent bez vlastního zápisu zapíše jen řádek outboxu.
3. Relay (background worker) po zápisu a na časovač: načte neodeslané, odešle v pořadí, označí; selhání = `attempts + 1` a další pokus po backoffu.
4. Odběratelé jsou idempotentní (Inbox, unikátní obchodní klíč, idempotency key), relay doručuje „aspoň jednou“; kde to neplatí, uveď v závěru.
5. Test přes broker s poruchou: (a) broker neběží → po obnově všechny zprávy v pořadí; (b) výpadek mezi zápisem a publikací; (c) ztracené potvrzení → duplicita, efekt jednou. Kontrola: bez outboxu (b) padá.

Na co si dát pozor:
- Více instancí relay: `SKIP LOCKED` jen nad prvním neodeslaným řádkem agregátu a zámek s lease, jinak druhá instance předběhne první; nebo jedna instance.
- Zpráva, kterou broker trvale odmítá, zablokuje svůj agregát: alarm na stáří outboxu.

## 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 výpadku brokeru (a) až (c) a kontrola bez outboxu.
- Zápis stavu a outboxu je atomický (test s chybou uvnitř transakce).
- Relay ve více instancích bez dvojí publikace a s pořadím v agregátu (test), nebo zdokumentovaná jedna instance.
- 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: Transactional Outbox

Stack: C#. Režim: challenge.
Cíl: Nahradit přímou publikaci po zápisu transakčním Outboxem s relay procesem.

## 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 producenty, kteří po zápisu publikují. Pokud ne, nejdřív založ minimálního producenta: zápis stavu a `publish` do brokeru v paměti.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Všechna místa, kde se po `save` volá `publish`/`send` (dual write), i v konzumentech, a kde je u každého zápis stavu (stejná databáze, jiná služba, žádný).
- Zda broker knihovna projektu už Outbox nabízí (event store s relayem z feedu už outboxem je).
- Transakční hranici (jedna DB transakce).
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (outbox, relay), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. Když chybí, navrhni ji v plánu.

## Očekávané chování

Zápis stavu a publikace jsou dvě operace nad dvěma systémy: spadne-li mezi nimi služba nebo broker, stav je uložený, ale nikdo se o něm nedozví a proces stojí. Outbox zapíše řádek „k odeslání“ v téže transakci jako stav a relay ho doručuje, dokud neuspěje. Doručuje „aspoň jednou“, s Inboxem u příjemce vzniká efektivně „právě jednou“. Příklad: broker odmítá 70 % publikací; proces zaostává, ale neztratí se nic.

## Zadání (Challenge)

Zaruč, že každá uložená událost bude dříve nebo později publikována, i když broker nebo služba mezitím selžou.

Technická specifika (C#): Transakce `DbContext`, relay jako `BackgroundService`; nejdřív zkontroluj outbox v messaging knihovně projektu.

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 výpadku brokeru (a) až (c) a kontrola bez outboxu.
- Zápis stavu a outboxu je atomický (test s chybou uvnitř transakce).
- Relay ve více instancích bez dvojí publikace a s pořadím v agregátu (test), nebo zdokumentovaná jedna instance.
- 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: Transactional Outbox

Stack: Web (HTML/JS nebo stack aplikace). Režim: s vedením.
Cíl: Nahradit přímou publikaci po zápisu transakčním Outboxem s relay procesem.

## 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 producenty, kteří po zápisu publikují. Pokud ne, nejdřív založ minimálního producenta: zápis stavu a `publish` do brokeru v paměti.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Všechna místa, kde se po `save` volá `publish`/`send` (dual write), i v konzumentech, a kde je u každého zápis stavu (stejná databáze, jiná služba, žádný).
- Zda broker knihovna projektu už Outbox nabízí (event store s relayem z feedu už outboxem je).
- Transakční hranici (jedna DB transakce).
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (outbox, relay), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. Když chybí, navrhni ji v plánu.

## Očekávané chování

Zápis stavu a publikace jsou dvě operace nad dvěma systémy: spadne-li mezi nimi služba nebo broker, stav je uložený, ale nikdo se o něm nedozví a proces stojí. Outbox zapíše řádek „k odeslání“ v téže transakci jako stav a relay ho doručuje, dokud neuspěje. Doručuje „aspoň jednou“, s Inboxem u příjemce vzniká efektivně „právě jednou“. Příklad: broker odmítá 70 % publikací; proces zaostává, ale neztratí se nic.

## Konkrétní úkol

Technická specifika (Web (HTML/JS nebo stack aplikace)): Outbox na backendu; ve frontendu volitelně ukládej do IndexedDB „outbox“ jen bezpečně opakovatelné příkazy (stejný `X-Correlation-Id`) a odesílej při `online`.

Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení:
1. Plán: schéma tabulky outbox (id, type, topic, payload, headers, aggregate_key, position, created_at, sent_at, attempts, next_attempt_at, locked_until) a kde žije, když je stav v jiné službě.
2. Zápis stavu a outbox řádku v jedné transakci; producent bez vlastního zápisu zapíše jen řádek outboxu.
3. Relay (background worker) po zápisu a na časovač: načte neodeslané, odešle v pořadí, označí; selhání = `attempts + 1` a další pokus po backoffu.
4. Odběratelé jsou idempotentní (Inbox, unikátní obchodní klíč, idempotency key), relay doručuje „aspoň jednou“; kde to neplatí, uveď v závěru.
5. Test přes broker s poruchou: (a) broker neběží → po obnově všechny zprávy v pořadí; (b) výpadek mezi zápisem a publikací; (c) ztracené potvrzení → duplicita, efekt jednou. Kontrola: bez outboxu (b) padá.

Na co si dát pozor:
- Více instancí relay: `SKIP LOCKED` jen nad prvním neodeslaným řádkem agregátu a zámek s lease, jinak druhá instance předběhne první; nebo jedna instance.
- Zpráva, kterou broker trvale odmítá, zablokuje svůj agregát: alarm na stáří outboxu.

## 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 výpadku brokeru (a) až (c) a kontrola bez outboxu.
- Zápis stavu a outboxu je atomický (test s chybou uvnitř transakce).
- Relay ve více instancích bez dvojí publikace a s pořadím v agregátu (test), nebo zdokumentovaná jedna instance.
- 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: Transactional Outbox

Stack: Web (HTML/JS nebo stack aplikace). Režim: challenge.
Cíl: Nahradit přímou publikaci po zápisu transakčním Outboxem s relay procesem.

## 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 producenty, kteří po zápisu publikují. Pokud ne, nejdřív založ minimálního producenta: zápis stavu a `publish` do brokeru v paměti.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Všechna místa, kde se po `save` volá `publish`/`send` (dual write), i v konzumentech, a kde je u každého zápis stavu (stejná databáze, jiná služba, žádný).
- Zda broker knihovna projektu už Outbox nabízí (event store s relayem z feedu už outboxem je).
- Transakční hranici (jedna DB transakce).
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (outbox, relay), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji. Když chybí, navrhni ji v plánu.

## Očekávané chování

Zápis stavu a publikace jsou dvě operace nad dvěma systémy: spadne-li mezi nimi služba nebo broker, stav je uložený, ale nikdo se o něm nedozví a proces stojí. Outbox zapíše řádek „k odeslání“ v téže transakci jako stav a relay ho doručuje, dokud neuspěje. Doručuje „aspoň jednou“, s Inboxem u příjemce vzniká efektivně „právě jednou“. Příklad: broker odmítá 70 % publikací; proces zaostává, ale neztratí se nic.

## Zadání (Challenge)

Zaruč, že každá uložená událost bude dříve nebo později publikována, i když broker nebo služba mezitím selžou.

Technická specifika (Web (HTML/JS nebo stack aplikace)): Outbox na backendu; ve frontendu volitelně ukládej do IndexedDB „outbox“ jen bezpečně opakovatelné příkazy (stejný `X-Correlation-Id`) a odesílej při `online`.

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 výpadku brokeru (a) až (c) a kontrola bez outboxu.
- Zápis stavu a outboxu je atomický (test s chybou uvnitř transakce).
- Relay ve více instancích bez dvojí publikace a s pořadím v agregátu (test), nebo zdokumentovaná jedna instance.
- 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á.

Š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í