Cvičení 03 · Čtecí model z událostí, oprava chyby přepočtem

Projekce a replay

  • projection
  • replay
  • vedlejší účinky

Princip

Projekce je čtecí model odvozený z událostí (tady souhrn kalkulace: počet změn příjmu, sazby, poslední příjem).

Chyba v projekci není chyba v historii. Opravíme kód projekce a přehrajeme události znovu (rebuild).

Pozor na vedlejší účinky: při replayi se nesmí znovu odeslat e-mail ani strhnout platba. Přestavba pohledu je oddělená od provádění skutečných operací.

Co sledovat

  • Počet změn příjmu v projekci v1 nesedí s počtem událostí IncomeChanged.
  • Rebuild bez potlačení účinků pošle klientovi e-mail znovu (vpravo „Příčina → Následek“).

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

Bez řešení

Spustit chybnou projekci v1

Projekce v1 počítá změnu sazby jako změnu příjmu. Po opravě provedeme rebuild, ale replay nepotlačí vedlejší účinky.

Spustit v simulátoru bez řešení

S řešením

Spustit opravu: projekce v2 + replay bez účinků

Projekce v2 počítá správně, rebuild běží v režimu bez vedlejších účinků. Historie zůstala beze změny, jen se znovu odvodil pohled.

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

Co udělat: Klikni na „Spustit chybnou projekci v1“. Na co se dívat: Po přestavbě projekce klientovi odejde e-mail podruhé. 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.

Přidat projekci nad event stream kalkulačky a umět ji kdykoli přestavět, aniž by se opakovaly vedlejší účinky.

Jazyk
Varianta
# Úkol pro coding agenta: Projekce a replay

Stack: Java. Režim: s vedením.
Cíl: Přidat projekci nad event stream kalkulačky a umět ji kdykoli přestavět, aniž by se opakovaly vedlejší účinky.

## 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á event store výpočtů (Event Sourcing). Pokud ne, nejdřív založ minimální: události `{ streamId, version, type, payload }` jen přidávané na konec.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Kde dnes vznikají souhrny/reporty z dat kalkulací.
- Kód, který při dokončení kalkulace posílá e-mail nebo jiný vedlejší účinek. Pokud žádný není, navrhni e-mail při `CalculationCompleted` přes in-memory `Mailer`.
- Event store (nebo stream, který ho nahrazuje). Pokud nemá globální pořadí zápisu napříč streamy (autoinkrement `position`), doplň ho; čas nestačí.
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (projekce, checkpoint), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji.

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

Projekce je čtecí model odvozený z událostí, tady souhrn výpočtu (počet změn příjmu a sazby, poslední příjem). Chyba v projekci není chyba v historii: opravíš kód a přehraješ události znovu (rebuild) bez opakování vedlejších účinků. Příklad: projekce v1 počítá změnu sazby jako změnu příjmu; po opravě a rebuildu počet změn příjmu sedí s počtem `IncomeChanged` a e-mail o dokončení podruhé neodejde.

## Konkrétní úkol

Technická specifika (Java): Projekci drž v samostatné tabulce, zpracování jako `@Scheduled` poller nebo listener nad event store s uloženým offsetem.

Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení:
1. Plán: popiš projekci (pole, jaké události ji mění) a kde bude uložená. Výchozí návrh: souhrn z „Očekávaného chování“.
2. Implementuj handler projekce jako čistou funkci `(model, event) -> model` a ukládej pozici posledně zpracované události.
3. Přidej příkaz `rebuild`, který projekci smaže a přehraje od začátku.
4. Odděl vedlejší účinky: handler účinků se v režimu `replay` nespouští (explicitní příznak, ne zakomentovaný kód). Režim odvoď z `effectsPosition`, kterou rebuild nemaže, aby událost bez odeslaného e-mailu šla jako `live`.
5. Test: chybná verze projekce vrací špatné číslo, opravená po rebuildu správné; e-mail se při rebuildu neodešle.

Na co si dát pozor:
- Rebuild za běhu: co se stane s událostmi, které přijdou během přehrávání, a co mezitím vidí čtenář?
- Idempotence obou handlerů (projekce i e-mailu) při opakovaném zpracování stejné události.

## 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ž

- Projekce je pouze odvozená; po smazání a rebuildu je identická.
- Rebuild neodešle e-mail ani nevolá externí službu.
- Událost, která přijde během rebuildu, je v projekci a její e-mail odešel právě jednou.
- Pozice zpracování je uložená, běh je navazující.
- 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: Projekce a replay

Stack: Java. Režim: challenge.
Cíl: Přidat projekci nad event stream kalkulačky a umět ji kdykoli přestavět, aniž by se opakovaly vedlejší účinky.

## 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á event store výpočtů (Event Sourcing). Pokud ne, nejdřív založ minimální: události `{ streamId, version, type, payload }` jen přidávané na konec.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Kde dnes vznikají souhrny/reporty z dat kalkulací.
- Kód, který při dokončení kalkulace posílá e-mail nebo jiný vedlejší účinek. Pokud žádný není, navrhni e-mail při `CalculationCompleted` přes in-memory `Mailer`.
- Event store (nebo stream, který ho nahrazuje). Pokud nemá globální pořadí zápisu napříč streamy (autoinkrement `position`), doplň ho; čas nestačí.
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (projekce, checkpoint), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji.

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

Projekce je čtecí model odvozený z událostí, tady souhrn výpočtu (počet změn příjmu a sazby, poslední příjem). Chyba v projekci není chyba v historii: opravíš kód a přehraješ události znovu (rebuild) bez opakování vedlejších účinků. Příklad: projekce v1 počítá změnu sazby jako změnu příjmu; po opravě a rebuildu počet změn příjmu sedí s počtem `IncomeChanged` a e-mail o dokončení podruhé neodejde.

## Zadání (Challenge)

Přidej přestavitelnou projekci souhrnu kalkulace a prokaž testem, že rebuild opraví chybu a nespustí žádný vedlejší účinek.

Technická specifika (Java): Projekci drž v samostatné tabulce, zpracování jako `@Scheduled` poller nebo listener nad event store s uloženým offsetem.

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ž

- Projekce je pouze odvozená; po smazání a rebuildu je identická.
- Rebuild neodešle e-mail ani nevolá externí službu.
- Událost, která přijde během rebuildu, je v projekci a její e-mail odešel právě jednou.
- Pozice zpracování je uložená, běh je navazující.
- 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: Projekce a replay

Stack: C#. Režim: s vedením.
Cíl: Přidat projekci nad event stream kalkulačky a umět ji kdykoli přestavět, aniž by se opakovaly vedlejší účinky.

## 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á event store výpočtů (Event Sourcing). Pokud ne, nejdřív založ minimální: události `{ streamId, version, type, payload }` jen přidávané na konec.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Kde dnes vznikají souhrny/reporty z dat kalkulací.
- Kód, který při dokončení kalkulace posílá e-mail nebo jiný vedlejší účinek. Pokud žádný není, navrhni e-mail při `CalculationCompleted` přes in-memory `Mailer`.
- Event store (nebo stream, který ho nahrazuje). Pokud nemá globální pořadí zápisu napříč streamy (autoinkrement `position`), doplň ho; čas nestačí.
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (projekce, checkpoint), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji.

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

Projekce je čtecí model odvozený z událostí, tady souhrn výpočtu (počet změn příjmu a sazby, poslední příjem). Chyba v projekci není chyba v historii: opravíš kód a přehraješ události znovu (rebuild) bez opakování vedlejších účinků. Příklad: projekce v1 počítá změnu sazby jako změnu příjmu; po opravě a rebuildu počet změn příjmu sedí s počtem `IncomeChanged` a e-mail o dokončení podruhé neodejde.

## Konkrétní úkol

Technická specifika (C#): Projekce jako `BackgroundService` čtoucí event store od uloženého checkpointu; účinky za samostatným rozhraním, které se při rebuildu nepoužije.

Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení:
1. Plán: popiš projekci (pole, jaké události ji mění) a kde bude uložená. Výchozí návrh: souhrn z „Očekávaného chování“.
2. Implementuj handler projekce jako čistou funkci `(model, event) -> model` a ukládej pozici posledně zpracované události.
3. Přidej příkaz `rebuild`, který projekci smaže a přehraje od začátku.
4. Odděl vedlejší účinky: handler účinků se v režimu `replay` nespouští (explicitní příznak, ne zakomentovaný kód). Režim odvoď z `effectsPosition`, kterou rebuild nemaže, aby událost bez odeslaného e-mailu šla jako `live`.
5. Test: chybná verze projekce vrací špatné číslo, opravená po rebuildu správné; e-mail se při rebuildu neodešle.

Na co si dát pozor:
- Rebuild za běhu: co se stane s událostmi, které přijdou během přehrávání, a co mezitím vidí čtenář?
- Idempotence obou handlerů (projekce i e-mailu) při opakovaném zpracování stejné události.

## 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ž

- Projekce je pouze odvozená; po smazání a rebuildu je identická.
- Rebuild neodešle e-mail ani nevolá externí službu.
- Událost, která přijde během rebuildu, je v projekci a její e-mail odešel právě jednou.
- Pozice zpracování je uložená, běh je navazující.
- 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: Projekce a replay

Stack: C#. Režim: challenge.
Cíl: Přidat projekci nad event stream kalkulačky a umět ji kdykoli přestavět, aniž by se opakovaly vedlejší účinky.

## 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á event store výpočtů (Event Sourcing). Pokud ne, nejdřív založ minimální: události `{ streamId, version, type, payload }` jen přidávané na konec.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Kde dnes vznikají souhrny/reporty z dat kalkulací.
- Kód, který při dokončení kalkulace posílá e-mail nebo jiný vedlejší účinek. Pokud žádný není, navrhni e-mail při `CalculationCompleted` přes in-memory `Mailer`.
- Event store (nebo stream, který ho nahrazuje). Pokud nemá globální pořadí zápisu napříč streamy (autoinkrement `position`), doplň ho; čas nestačí.
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (projekce, checkpoint), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji.

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

Projekce je čtecí model odvozený z událostí, tady souhrn výpočtu (počet změn příjmu a sazby, poslední příjem). Chyba v projekci není chyba v historii: opravíš kód a přehraješ události znovu (rebuild) bez opakování vedlejších účinků. Příklad: projekce v1 počítá změnu sazby jako změnu příjmu; po opravě a rebuildu počet změn příjmu sedí s počtem `IncomeChanged` a e-mail o dokončení podruhé neodejde.

## Zadání (Challenge)

Přidej přestavitelnou projekci souhrnu kalkulace a prokaž testem, že rebuild opraví chybu a nespustí žádný vedlejší účinek.

Technická specifika (C#): Projekce jako `BackgroundService` čtoucí event store od uloženého checkpointu; účinky za samostatným rozhraním, které se při rebuildu nepoužije.

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ž

- Projekce je pouze odvozená; po smazání a rebuildu je identická.
- Rebuild neodešle e-mail ani nevolá externí službu.
- Událost, která přijde během rebuildu, je v projekci a její e-mail odešel právě jednou.
- Pozice zpracování je uložená, běh je navazující.
- 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: Projekce a replay

Stack: Web (HTML/JS nebo stack aplikace). Režim: s vedením.
Cíl: Přidat projekci nad event stream kalkulačky a umět ji kdykoli přestavět, aniž by se opakovaly vedlejší účinky.

## 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á event store výpočtů (Event Sourcing). Pokud ne, nejdřív založ minimální: události `{ streamId, version, type, payload }` jen přidávané na konec.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Kde dnes vznikají souhrny/reporty z dat kalkulací.
- Kód, který při dokončení kalkulace posílá e-mail nebo jiný vedlejší účinek. Pokud žádný není, navrhni e-mail při `CalculationCompleted` přes in-memory `Mailer`.
- Event store (nebo stream, který ho nahrazuje). Pokud nemá globální pořadí zápisu napříč streamy (autoinkrement `position`), doplň ho; čas nestačí.
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (projekce, checkpoint), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji.

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

Projekce je čtecí model odvozený z událostí, tady souhrn výpočtu (počet změn příjmu a sazby, poslední příjem). Chyba v projekci není chyba v historii: opravíš kód a přehraješ události znovu (rebuild) bez opakování vedlejších účinků. Příklad: projekce v1 počítá změnu sazby jako změnu příjmu; po opravě a rebuildu počet změn příjmu sedí s počtem `IncomeChanged` a e-mail o dokončení podruhé neodejde.

## Konkrétní úkol

Technická specifika (Web (HTML/JS nebo stack aplikace)): Projekce jako reducer nad událostmi v pořadí `position`; read model a checkpoint (`position`, `effectsPosition`) ukládej v jedné transakci, checkpoint samostatně.

Postupuj po krocích. Po bodu 1 (plán) napiš, co zjistíš a co navrhuješ, a počkej na potvrzení:
1. Plán: popiš projekci (pole, jaké události ji mění) a kde bude uložená. Výchozí návrh: souhrn z „Očekávaného chování“.
2. Implementuj handler projekce jako čistou funkci `(model, event) -> model` a ukládej pozici posledně zpracované události.
3. Přidej příkaz `rebuild`, který projekci smaže a přehraje od začátku.
4. Odděl vedlejší účinky: handler účinků se v režimu `replay` nespouští (explicitní příznak, ne zakomentovaný kód). Režim odvoď z `effectsPosition`, kterou rebuild nemaže, aby událost bez odeslaného e-mailu šla jako `live`.
5. Test: chybná verze projekce vrací špatné číslo, opravená po rebuildu správné; e-mail se při rebuildu neodešle.

Na co si dát pozor:
- Rebuild za běhu: co se stane s událostmi, které přijdou během přehrávání, a co mezitím vidí čtenář?
- Idempotence obou handlerů (projekce i e-mailu) při opakovaném zpracování stejné události.

## 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ž

- Projekce je pouze odvozená; po smazání a rebuildu je identická.
- Rebuild neodešle e-mail ani nevolá externí službu.
- Událost, která přijde během rebuildu, je v projekci a její e-mail odešel právě jednou.
- Pozice zpracování je uložená, běh je navazující.
- 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: Projekce a replay

Stack: Web (HTML/JS nebo stack aplikace). Režim: challenge.
Cíl: Přidat projekci nad event stream kalkulačky a umět ji kdykoli přestavět, aniž by se opakovaly vedlejší účinky.

## 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á event store výpočtů (Event Sourcing). Pokud ne, nejdřív založ minimální: události `{ streamId, version, type, payload }` jen přidávané na konec.

Nejdřív čti, nic neměň. Najdi a stručně shrň:
- Kde dnes vznikají souhrny/reporty z dat kalkulací.
- Kód, který při dokončení kalkulace posílá e-mail nebo jiný vedlejší účinek. Pokud žádný není, navrhni e-mail při `CalculationCompleted` přes in-memory `Mailer`.
- Event store (nebo stream, který ho nahrazuje). Pokud nemá globální pořadí zápisu napříč streamy (autoinkrement `position`), doplň ho; čas nestačí.
- Které z těchto částí už v projektu existují a které chybí. Než napíšeš vlastní infrastrukturu (projekce, checkpoint), ověř, jestli ji projekt nebo organizace nemá jako hotovou knihovnu, a použij ji.

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

Projekce je čtecí model odvozený z událostí, tady souhrn výpočtu (počet změn příjmu a sazby, poslední příjem). Chyba v projekci není chyba v historii: opravíš kód a přehraješ události znovu (rebuild) bez opakování vedlejších účinků. Příklad: projekce v1 počítá změnu sazby jako změnu příjmu; po opravě a rebuildu počet změn příjmu sedí s počtem `IncomeChanged` a e-mail o dokončení podruhé neodejde.

## Zadání (Challenge)

Přidej přestavitelnou projekci souhrnu kalkulace a prokaž testem, že rebuild opraví chybu a nespustí žádný vedlejší účinek.

Technická specifika (Web (HTML/JS nebo stack aplikace)): Projekce jako reducer nad událostmi v pořadí `position`; read model a checkpoint (`position`, `effectsPosition`) ukládej v jedné transakci, checkpoint samostatně.

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ž

- Projekce je pouze odvozená; po smazání a rebuildu je identická.
- Rebuild neodešle e-mail ani nevolá externí službu.
- Událost, která přijde během rebuildu, je v projekci a její e-mail odešel právě jednou.
- Pozice zpracování je uložená, běh je navazující.
- 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í