ЁЯУМ рдзрдбрд╛ 07 тАФ Event-driven architecture рдЖрдгрд┐ CQRS: рд╕реВрдЪрдирд╛ рдлрд▓рдХ рдЖрдгрд┐ display board
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 07 ┬╖ рдорд╛рдЧрдЪрд╛: lesson-06-styles ┬╖ рдкреБрдврдЪрд╛: lesson-08-data-ownership
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ06, рдЖрдгрд┐ рдПрдХ рд╡реЗрдЧрд│реНрдпрд╛ рдкреНрд░рдХрд╛рд░рдЪреА рдорд╛рд░реНрдЧрд┐рдХрд╛. Admissions рдЖрддрд╛ grades, fees рдЖрдгрд┐ timetable рд▓рд╛
call рдХрд░рдд рдирд╛рд╣реА; рддреЗ рдПрдХ event publish рдХрд░рддреЗ тАФ "рдПрдХ рд╡рд┐рджреНрдпрд╛рд░реНрдерд┐рдиреА рджрд╛рдЦрд▓ рдЭрд╛рд▓реА" тАФ рдЖрдгрд┐ рдЬреНрдпрд╛рд▓рд╛
рддреНрдпрд╛рдд рд░рд╕ рдЖрд╣реЗ рддреЛ subscribe рдХрд░рддреЛ. рдордЧ CQRS: рдЬреНрдпрд╛ model рдордзреНрдпреЗ рддреБрдореНрд╣реА рд▓рд┐рд╣рд┐рддрд╛ рддреЗ, рдЬреНрдпрд╛
model рдордзреВрди рддреБрдореНрд╣реА рд╡рд╛рдЪрддрд╛ рддреНрдпрд╛рдкрд╛рд╕реВрди рд╡реЗрдЧрд│реЗ рдареЗрд╡рд╛, рдЖрдгрд┐ рд╡рд╛рдЪрдирд╛рдЪреА рдмрд╛рдЬреВ рдереЛрдбреА рдорд╛рдЧреЗ рдЕрд╕рддреЗ рд╣реЗ рд╕реНрд╡реАрдХрд╛рд░рд╛.
EventBus рдЖрдгрд┐ ReportCardProjection arch/models.py рдордзреНрдпреЗ, events()
arch/demo.py рдордзреНрдпреЗ. System Design рд╢рд╛рд│реЗрдЪрд╛
events, pub/sub рдЖрдгрд┐ outbox
рд╡рд░рдЪрд╛ рдзрдбрд╛ delivery рдЖрдгрд┐ outbox рд╢рд┐рдХрд╡рддреЛ; рд╣рд╛ рдзрдбрд╛ events рдореБрд│реЗ coupling рдЪреЗ рдХрд╛рдп рд╣реЛрддреЗ рдпрд╛рдмрджреНрджрд▓ рдЖрд╣реЗ.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╢рд╛рд│реЗрдд рдирд╡реАрди рдореВрд▓ рдЖрд▓реЗ рдХреА admissions office рдЖрдзреА рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧрд╛рдХрдбреЗ рдЪрд╛рд▓рдд рдЬрд╛рдпрдЪреЗ, рдордЧ рд╣рд┐рд╢реЛрдм рд╡рд┐рднрд╛рдЧрд╛рдХрдбреЗ, рдордЧ timetable office рдХрдбреЗ, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХрд╛рд▓рд╛ рд╕рд╛рдВрдЧрд╛рдпрдЪреЗ. ЁЯЪ╢тАНтЩАя╕П рдирд╡реАрди рд╡рд╛рдЪрдирд╛рд▓рдп рд╕реБрд░реВ рдЭрд╛рд▓реЗ рддрд░ admissions рд▓рд╛ рдЪреМрдереА рдлреЗрд░реА рд╢рд┐рдХрд╛рд╡реА рд▓рд╛рдЧрд╛рдпрдЪреА.
рдЖрддрд╛ рд╕рднрд╛рдЧреГрд╣рд╛рдд рдПрдХ рд╕реВрдЪрдирд╛ рдлрд▓рдХ ЁЯУМ рдЖрд╣реЗ. Admissions рдПрдХрдЪ рд╕реВрдЪрдирд╛ рд▓рд╛рд╡рддреЗ: "рджреАрдкрд┐рдХрд╛ 5A рд╡рд░реНрдЧрд╛рдд рджрд╛рдЦрд▓ рдЭрд╛рд▓реА." рдПрд╡рдвреЗрдЪ. рдкрд░реАрдХреНрд╖рд╛ рд╡рд┐рднрд╛рдЧ, рд╣рд┐рд╢реЛрдм рд╡рд┐рднрд╛рдЧ рдЖрдгрд┐ timetable office рдкреНрд░рддреНрдпреЗрдХрдЬрдг рдлрд▓рдХ рд╡рд╛рдЪрддреЛ рдЖрдгрд┐ рдЖрдкрд▓реЗ рдХрд╛рдо рдХрд░рддреЛ. рд╡рд╛рдЪрдирд╛рд▓рдп рд╕реБрд░реВ рдЭрд╛рд▓реЗ рдХреА рдЧреНрд░рдВрдердкрд╛рд▓ рдлрдХреНрдд рдлрд▓рдХ рд╡рд╛рдЪрд╛рдпрд▓рд╛ рд▓рд╛рдЧрддрд╛рдд тАФ admissions рдордзреНрдпреЗ рдХрд╛рд╣реАрдЪ рдмрджрд▓ рд╣реЛрдд рдирд╛рд╣реА.
рдЖрдгрд┐ рдЧреБрдг? рд╢рд┐рдХреНрд╖рд┐рдХрд╛ рдЧреБрдг рдиреЛрдВрджрд╡рд╣реАрдд рд▓рд┐рд╣рд┐рддреЗ (рд▓рд┐рдЦрд╛рдг). рд╕рднрд╛рдЧреГрд╣рд╛рддреАрд▓ display board рдкреНрд░рддреНрдпреЗрдХ рдореБрд▓рд╛рдЪреА рд╕рд░рд╛рд╕рд░реА рджрд╛рдЦрд╡рддреЛ (рд╡рд╛рдЪрди). рдХреЛрдгреАрддрд░реА display board рдереЛрдбреНрдпрд╛ рд╡реЗрд│рд╛рдиреЗ рдЕрджреНрдпрдпрд╛рд╡рдд рдХрд░рддреЗ. рдХрд╛рд╣реА рдорд┐рдирд┐рдЯреЗ рдлрд▓рдХрд╛рд╡рд░ рдЬреБрдиреА рд╕рд░рд╛рд╕рд░реА рджрд┐рд╕реВ рд╢рдХрддреЗ. рдЬрд▓рдж, рд╕рд╛рдзреНрдпрд╛ рдлрд▓рдХрд╛рдЪреА рд╣реА рдХрд┐рдВрдордд рдЖрд╣реЗ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
adm["ЁЯЧВя╕П admissions"] -->|"publish StudentAdmitted(Dipika, 5A)"| board["ЁЯУМ notice board<br/>(event bus)"]
board --> gr["ЁЯУЭ grades: opens a mark sheet"]
board --> fee["ЁЯТ░ fees: opens an account"]
board --> tt["ЁЯЧУя╕П timetable: assigns a class"]
board -.-> lib["ЁЯУЦ library (new): no change to admissions"]
subgraph cqrs["CQRS"]
w["тЬНя╕П write side: marks 72, 85, 90"] -->|"MarkRecorded events"| proj["ЁЯФД projection"]
proj --> r["ЁЯУ║ read side: average 78.5 тЖТ 82.33"]
end
ЁЯЧ║я╕П рдХрд╛рдврд▓реЗрд▓реА рдЖрдХреГрддреА + рдПрдХ lab: https://school-edh.pages.dev/software-architecture/lesson-diagrams.html#l07
тЭУ рдХрд╛рдп
- Event тАФ рдЖрдзреАрдЪ рдШрдбреВрди рдЧреЗрд▓реЗрд▓реА рд╡рд╕реНрддреБрд╕реНрдерд┐рддреА, рднреВрддрдХрд╛рд│реА рдирд╛рд╡рд╛рдиреЗ:
StudentAdmitted,MarkRecorded,FeePaid. Command рдХрд╛рд╣реАрддрд░реА рдШрдбрд╛рд╡реЗ рдЕрд╢реА рд╡рд┐рдирдВрддреА рдХрд░рддреЗ (EnrolStudent) рдЖрдгрд┐ рддреА рдирд╛рдХрд╛рд░рд▓реА рдЬрд╛рдК рд╢рдХрддреЗ; event рдирд╛рдХрд╛рд░рддрд╛ рдпреЗрдд рдирд╛рд╣реА. - Event-driven architecture тАФ рднрд╛рдЧ events publish рдХрд░реВрди рдЖрдгрд┐ рддреНрдпрд╛рдВрдирд╛ рдкреНрд░рддрд┐рд╕рд╛рдж рджреЗрдКрди рдмреЛрд▓рддрд╛рдд.
Martin Fowler рд▓реЛрдХ рдпрд╛рдЪреЗ рдЬреЗ рдЪрд╛рд░ рдЕрд░реНрде рдШреЗрддрд╛рдд рддреЗ рд╡реЗрдЧрд│реЗ рдХрд░рддрд╛рдд:
- event notification тАФ "рдХрд╛рд╣реАрддрд░реА рдШрдбрд▓реЗ; рддрдкрд╢реАрд▓ рд╣рд╡рд╛ рдЕрд╕реЗрд▓ рддрд░ рдорд▓рд╛ рд╡рд┐рдЪрд╛рд░рд╛"
- event-carried state transfer тАФ event рд╕реЛрдмрддрдЪ data рдпреЗрддреЛ, рдореНрд╣рдгреВрди listeners рдирд╛ рдкрд░рдд call рдХрд░рд╛рд╡рд╛ рд▓рд╛рдЧрдд рдирд╛рд╣реА
- event sourcing тАФ events рд╣реЗрдЪ рд╕рддреНрдпрд╛рдЪрд╛ рд╕реНрд░реЛрдд; state рддреНрдпрд╛рдВрдЪреНрдпрд╛рдкрд╛рд╕реВрди рдкреБрдиреНрд╣рд╛ рддрдпрд╛рд░ рд╣реЛрддреЗ
- CQRS тАФ рдЕрдиреЗрдХрджрд╛ events рд╕реЛрдмрдд рд╡рд╛рдкрд░рд▓реЗ рдЬрд╛рддреЗ, рдкрдг рд╣реА рд╡реЗрдЧрд│реА рдХрд▓реНрдкрдирд╛ рдЖрд╣реЗ (рдЦрд╛рд▓реА)
- Publish / subscribe тАФ publisher рд▓рд╛ рдХреЛрдг рдРрдХрддреЗ рд╣реЗ рдорд╛рд╣реАрдд рдирд╕рддреЗ. Coupling "рдореА рдХреЛрдгрд╛рд▓рд╛ call рдХрд░реВ" рд╡рд░реВрди "event рдХрд╕рд╛ рджрд┐рд╕рддреЛ" рдХрдбреЗ рд╕рд░рдХрддреЗ тАФ event рдЪреЗ schema рд╣рд╛рдЪ рдХрд░рд╛рд░ рдмрдирддреЛ.
- CQRS (Command Query Responsibility Segregation) тАФ Greg Young рдпрд╛рдВрдиреА рджрд┐рд▓реЗрд▓реЗ рдирд╛рд╡: writes рд╕рд╛рдареА рдПрдХ model (commands, рдирд┐рдпрдо, consistency) рдЖрдгрд┐ reads рд╕рд╛рдареА рджреБрд╕рд░реЗ (queries, screen рд╕рд╛рдареА рдЖрдХрд╛рд░ рджрд┐рд▓реЗрд▓реЗ). рддреЗ Bertrand Meyer рдпрд╛рдВрдЪреНрдпрд╛ commandтАУquery separation рдордзреВрди рд╡рд╛рдврд▓реЗ.
- Projection / read model тАФ рд╡рд╛рдЪрдирд╛рдЪреА рдмрд╛рдЬреВ, events рд▓рд╛рдЧреВ рдХрд░реВрди рддрдпрд╛рд░ рдХреЗрд▓реЗрд▓реА. рдЗрдереЗ:
ReportCardProjectionрдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рджреНрдпрд╛рд░реНрдерд┐рдиреАрд╕рд╛рдареА count рдЖрдгрд┐ total рдареЗрд╡рддреЗ. - Eventual consistency тАФ write рдирдВрддрд░ read model рдереЛрдбреНрдпрд╛ рд╡реЗрд│рд╛рдиреЗ рдмрд░реЛрдмрд░ рд╣реЛрддреЗ, рдореНрд╣рдгрдЬреЗ events рд▓рд╛рдЧреВ рдХреЗрд▓реНрдпрд╛рд╡рд░. рдХрд┐рддреА рд╡реЗрд│рд╛рдиреЗ, рддреНрдпрд╛рд▓рд╛ lag рдореНрд╣рдгрддрд╛рдд.
- Choreography рд╡рд┐рд░реБрджреНрдз orchestration тАФ events рдореБрд│реЗ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧ рд╕реНрд╡рддрдГрд╣реВрди рдкреНрд░рддрд┐рд╕рд╛рдж рджреЗрддреЛ (choreography); рдкреНрд░рддреНрдпреЗрдХ рдкрд╛рдпрд░реАрд▓рд╛ рдХрд╛рдп рдХрд░рд╛рдпрдЪреЗ рддреЗ рд╕рд╛рдВрдЧрдгрд╛рд░рд╛ рд╕рдордиреНрд╡рдпрдХ рдореНрд╣рдгрдЬреЗ orchestration. Choreography рд╕реИрд▓ рдЕрд╕рддреЗ, рдкрдг рдкреВрд░реНрдг рдкреНрд░рд╡рд╛рд╣ рдкрд╛рд╣рдгреЗ рдХрдареАрдг рд╣реЛрддреЗ.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг рдкреНрд░рддреНрдпреЗрдХ рдереЗрдЯ call рд╣реА call рдХрд░рдгрд╛рд▒реНрдпрд╛рдХрдбреВрди call рд╣реЛрдгрд╛рд▒реНрдпрд╛рдХрдбреЗ рдЬрд╛рдгрд╛рд░реА рдорд╛рд░реНрдЧрд┐рдХрд╛ рдЖрд╣реЗ тАФ рддреАрди calls рдЕрд╕рд▓реЗрд▓реНрдпрд╛ admissions рдХрдбреЗ рддреАрди рдмрд╛рд╣реЗрд░ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдорд╛рд░реНрдЧрд┐рдХрд╛ рдЖрд╣реЗрдд, рдЖрдгрд┐ рдЪреМрдерд╛ рд╡рд┐рднрд╛рдЧ рдореНрд╣рдгрдЬреЗ admissions edit рдХрд░рдгреЗ. Events "рдорд▓рд╛ рд╕рдЧрд│реНрдпрд╛рдВрдирд╛ рд╕рд╛рдВрдЧрд╛рдпрд▓рд╛рдЪ рд╣рд╡реЗ" рдЪреЗ рд░реВрдкрд╛рдВрддрд░ "рдореА рдПрдХрджрд╛рдЪ рдЬрд╛рд╣реАрд░ рдХрд░рддреЗ" рдордзреНрдпреЗ рдХрд░рддрд╛рдд. Reads рдЖрдгрд┐ writes рдирд╛ рдЦреВрдк рд╡реЗрдЧрд│реЗ рдЖрдХрд╛рд░ рд╣рд╡реЗ рдЕрд╕рддрд╛рдд рддреЗрд╡реНрд╣рд╛ CQRS рдорджрдд рдХрд░рддреЗ тАФ report card screen рд▓рд╛ рд╕рд░рд╛рд╕рд░реА рд╣рд╡реА, рдирд┐рдпрдорд╛рдВрдирд╛ рд╕реНрд╡рддрдВрддреНрд░ рдЧреБрдг рд╣рд╡реЗрдд. рджреЛрдШрд╛рдВрдЪреАрд╣реА рдЦрд░реА рдХрд┐рдВрдордд рдЖрд╣реЗ: рдкреНрд░рд╡рд╛рд╣ рд╕рдордЬрд╛рдпрд▓рд╛ рдХрдареАрдг рд╣реЛрддреЛ, рдЖрдгрд┐ рд╡рд╛рдЪрдирд╛рдЪреА рдмрд╛рдЬреВ stale рдЕрд╕реВ рд╢рдХрддреЗ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
arch/models.py рдордзрд▓рд╛ EventBus рдкреНрд░рддреНрдпреЗрдХ event рдирд╛рд╡рд╛рд╕рд╛рдареА subscribers рдЪреА
рдпрд╛рджреА рдареЗрд╡рддреЛ рдЖрдгрд┐ рддреНрдпрд╛рдВрдирд╛ рддреНрдпрд╛рдВрдиреА subscribe рдХреЗрд▓реЗрд▓реНрдпрд╛ рдХреНрд░рдорд╛рдиреЗрдЪ call рдХрд░рддреЛ (рдореНрд╣рдгреВрди output рдирд┐рд╢реНрдЪрд┐рдд
рдЕрд╕рддреЛ; рдЦрд░реЗ brokers asynchronously рдкреЛрд╣реЛрдЪрд╡рддрд╛рдд). ReportCardProjection MarkRecorded events
pending рдордзреНрдпреЗ рд░рд╛рдВрдЧреЗрдд рдареЗрд╡рддреЗ рдЖрдгрд┐ рддреБрдореНрд╣реА catch_up(n) call рдХрд░рддрд╛ рддреЗрд╡реНрд╣рд╛рдЪ рддреЗ рд▓рд╛рдЧреВ рдХрд░рддреЗ тАФ рдПрдХрд╛ рд╡реЗрд│реА
n events тАФ рддреНрдпрд╛рдореБрд│реЗ read model рдмрд░реЛрдмрд░реАрд▓рд╛ рдпреЗрдгреНрдпрд╛рдЪреНрдпрд╛ рдЖрдзреА рдХрд╕реЗ рджрд┐рд╕рддреЗ рддреЗ рддреБрдореНрд╣реА рдкрд╛рд╣реВ рд╢рдХрддрд╛.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 arch/demo.py events
python3 - <<'EOF'
import sys; sys.path.insert(0, "arch"); from models import EventBus, ReportCardProjection
bus = EventBus()
for who in ("grades", "fees", "timetable", "library"):
bus.subscribe("StudentAdmitted", who, lambda d, w=who: f"{w} saw {d['student']}")
print(bus.publish("StudentAdmitted", {"student": "Aishwarya"}))
p = ReportCardProjection()
for v in (72, 85, 90): p.on_mark({"student": "Katrina", "value": v})
print("applied 0 тЖТ", p.average("Katrina"))
for _ in range(3):
p.catch_up(1); print(f"applied {p.applied} тЖТ {p.average('Katrina')}")
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
events рд╣реЗ рдЫрд╛рдкрддреЗ:
тФАтФА admissions publishes StudentAdmitted(Dipika, 5A) on the notice board тЖТ grades opens a mark sheet ┬╖ fees opens an account ┬╖ timetable assigns a class
direct calls: admissions imports 3 departments ┬╖ events: it imports 0 of them (only the event's shape) тАФ a 4th listener needs no change to admissions
тФАтФА CQRS: 3 marks written (72, 85, 90); the read model has applied 2 тЖТ average 78.5
after catch-up it has applied 3 тЖТ average 82.33 ┬╖ reads are fast, and eventually consistent
рддреБрдордЪрд╛ snippet рд╣реЗ рдЫрд╛рдкрддреЛ:
[('grades', 'grades saw Aishwarya'), ('fees', 'fees saw Aishwarya'), ('timetable', 'timetable saw Aishwarya'), ('library', 'library saw Aishwarya')]
applied 0 тЖТ None
applied 1 тЖТ 72.0
applied 2 тЖТ 78.5
applied 3 тЖТ 82.33
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рд╡рд╛рдЪрдирд╛рд▓рдп рдЪреМрдерд╛ listener рдореНрд╣рдгреВрди рдЬреЛрдбрд▓реЗ рдЧреЗрд▓реЗ рдЖрдгрд┐ admissions рдмрджрд▓рд▓реЗ рдирд╛рд╣реА тАФ publisher рдЪреНрдпрд╛
рд╡рд┐рднрд╛рдЧрд╛рдВрдХрдбреЗ рдЬрд╛рдгрд╛рд▒реНрдпрд╛ рдмрд╛рд╣реЗрд░рдЪреНрдпрд╛ рдорд╛рд░реНрдЧрд┐рдХрд╛ 3 рд╡рд░реВрди 0 рдЭрд╛рд▓реНрдпрд╛. Coupling рдирд╛рд╣реАрд╕реЗ рдЭрд╛рд▓реЗ рдирд╛рд╣реА: рдкреНрд░рддреНрдпреЗрдХ
listener рдЖрддрд╛ StudentAdmitted рдЪреНрдпрд╛ рдЖрдХрд╛рд░рд╛рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди рдЖрд╣реЗ, рдореНрд╣рдгреВрди рддреНрдпрд╛ рдЖрдХрд╛рд░рд╛рдЪреА API рдЗрддрдХреАрдЪ
рдХрд╛рд│рдЬреА рдШреНрдпрд╛рдпрд▓рд╛ рд╣рд╡реА. рдЖрдгрд┐ рдмрд░реЛрдмрд░реАрд▓рд╛ рдпреЗрдд рдЕрд╕рддрд╛рдирд╛ read model рдиреЗ рдПрдХрд╛рдЪ рдкреНрд░рд╢реНрдирд╛рдЪреА рддреАрди рд╡реЗрдЧрд╡реЗрдЧрд│реА рдЙрддреНрддрд░реЗ
рджрд╛рдЦрд╡рд▓реА: рдХрд╛рд╣реАрдЪ рдирд╛рд╣реА (None), 72.0, 78.5, рдЖрдгрд┐ рд╢реЗрд╡рдЯреА 82.33. рд╢рд┐рдХреНрд╖рд┐рдХреЗрдиреЗ рдЧреБрдг save рдХреЗрд▓реНрдпрд╛рд╡рд░ рд▓рдЧреЗрдЪ
рддреНрдпрд╛рддреВрди рд╡рд╛рдЪрдгрд╛рд░реА screen рдЬреБрдиреА рд╕рд░рд╛рд╕рд░реА рджрд╛рдЦрд╡реВ рд╢рдХрддреЗ тАФ рддреБрдореНрд╣реА рддреНрдпрд╛рд╕рд╛рдареА design рдХрд░рддрд╛ ("updatingтАж"
рджрд╛рдЦрд╡рд╛, рдХрд┐рдВрд╡рд╛ рд╕реНрд╡рддрдГрдЪреЗ write, write рдмрд╛рдЬреВрдХрдбреВрдирдЪ рд╡рд╛рдЪрд╛).
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- commands рд╕рд╛рд░рдЦреА рдирд╛рд╡реЗ рдЕрд╕рд▓реЗрд▓реЗ events (
SendWelcomeEmail) тАФ рддреЛ рд╡реЗрд╖ рдмрджрд▓рд▓реЗрд▓рд╛ call рдЖрд╣реЗ - outbox рд╢рд┐рд╡рд╛рдп event publish рдХрд░рдгреЗ рдЖрдгрд┐ database рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рдгреЗ тАФ рдПрдХ рдпрд╢рд╕реНрд╡реА рд╣реЛрдКрди рджреБрд╕рд░реЗ рдЕрдкрдпрд╢реА рд╣реЛрдК рд╢рдХрддреЗ
- рд╕рдЧрд│реАрдХрдбреЗ CQRS, рдЕрдЧрджреА рд╕рд╛рдзреНрдпрд╛ query рдиреЗ рднрд╛рдЧрдгрд╛рд▒реНрдпрд╛ screens рд╕рд╛рдареАрд╕реБрджреНрдзрд╛
- "рдЖрдкрд▓реНрдпрд╛рдХрдбреЗ events рдЖрд╣реЗрдд рдореНрд╣рдгреВрди" event sourcing рд╕реНрд╡реАрдХрд╛рд░рдгреЗ тАФ рддреНрдпрд╛рдиреЗ data рд╕рд╛рдард╡рдгреНрдпрд╛рдЪреА, migrate рдХрд░рдгреНрдпрд╛рдЪреА рдЖрдгрд┐ рджреБрд░реБрд╕реНрдд рдХрд░рдгреНрдпрд╛рдЪреА рдкрджреНрдзрдд рдмрджрд▓рддреЗ
- event schema versioning рдирд╛рд╣реА тАФ publisher рдордзрд▓рд╛ рдПрдХ рдмрджрд▓ рд╕рдЧрд│реЗ listeners рдПрдХрджрдо рдореЛрдбрддреЛ
- read model рд▓рд╛ рд╕рддреНрдпрд╛рдЪрд╛ рд╕реНрд░реЛрдд рдорд╛рдирдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ project рд╡рд░ тАФ рд╕рд╛рдзреЗ read model PostgreSQL рдордзрд▓реЗ materialized view рдЕрд╕реВ рд╢рдХрддреЗ,
рд╡реЗрд│рд╛рдкрддреНрд░рдХрд╛рдиреБрд╕рд╛рд░ рдХрд┐рдВрд╡рд╛ writes рдирдВрддрд░ refresh рдХреЗрд▓реЗрд▓реЗ (CONCURRENTLY рдкреНрд░рдХрд╛рд░рд╛рд▓рд╛ unique index рд▓рд╛рдЧрддреЛ,
рдЖрдгрд┐ рддреЛ readers рдирд╛ block рдХрд░рдд рдирд╛рд╣реА):
CREATE MATERIALIZED VIEW report_cards AS
SELECT roll_no, count(*) AS marks, round(avg(value), 2) AS average
FROM marks GROUP BY roll_no;
CREATE UNIQUE INDEX ON report_cards (roll_no);
REFRESH MATERIALIZED VIEW CONCURRENTLY report_cards;
рд╡рд┐рднрд╛рдЧрд╛рдВрдордзрд▓реЗ events рд╕рд╣рд╕рд╛ broker рдордзреВрди рдЬрд╛рддрд╛рдд. Kafka рд╕реЛрдмрдд (рдкреНрд░рддреНрдпреЗрдХ event рдкреНрд░рдХрд╛рд░рд╛рд╕рд╛рдареА рдПрдХ topic, рдРрдХрдгрд╛рд▒реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рднрд╛рдЧрд╛рд╕рд╛рдареА рдПрдХ consumer group):
kafka-topics.sh --bootstrap-server localhost:9092 --create --topic student-admitted --partitions 3
kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic student-admitted --group library
Event рдЪреЗ рд╡рд░реНрдгрди рдХрд░рд╛рд░ рдореНрд╣рдгреВрди рдХрд░рд╛ тАФ рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде schema registry рдордзреАрд▓ JSON Schema рдХрд┐рдВрд╡рд╛ Avro schema
рд╕реЛрдмрдд тАФ рдЖрдгрд┐ рддреНрдпрд╛рд▓рд╛ version рджреНрдпрд╛ (StudentAdmitted v2 рдПрдХ field рдЬреЛрдбрддреЗ; рдЬреБрдиреЗ listeners рддреНрдпрд╛рдХрдбреЗ
рджреБрд░реНрд▓рдХреНрд╖ рдХрд░рддрд╛рдд).
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ event рд╕рд╛рдареА рд▓рд┐рд╣реВрди рдареЗрд╡рд╛ тАФ рддреЛ рдХреЛрдг publish рдХрд░рддреЗ, рдХреЛрдг рдРрдХрддреЗ, рддреНрдпрд╛рдЪреЗ schema version, рдЖрдгрд┐ рд╡рд╛рдЪрдирд╛рдЪреА рдмрд╛рдЬреВ рдЬрд╛рд╕реНрддреАрдд рдЬрд╛рд╕реНрдд рдХрд┐рддреА lag рджрд╛рдЦрд╡реВ рд╢рдХрддреЗ. "рдХреЛрдг рдРрдХрддреЗ?" рдпрд╛рдЪреЗ рдЙрддреНрддрд░ рдХреЛрдгрд╛рд▓рд╛рдЪ рджреЗрддрд╛ рдпреЗрдд рдирд╕реЗрд▓, рддрд░ рддреБрдореНрд╣реА рддреБрдордЪреНрдпрд╛ рдорд╛рд░реНрдЧрд┐рдХрд╛рдВрдЪрд╛ рдорд╛рдЧ рдЧрдорд╛рд╡рд▓рд╛ рдЖрд╣реЗ.
тПня╕П рдкреБрдвреЗ
Events рд╡рд┐рднрд╛рдЧрд╛рдВрдордзреНрдпреЗ data рд╡рд╛рд╣реВрди рдиреЗрддрд╛рдд. рдордЧ data рдЪреА рдорд╛рд▓рдХреА рдХреЛрдгрд╛рдХрдбреЗ тАФ рдЖрдгрд┐ рджреБрд╕рд░рд╛ рд╡рд┐рднрд╛рдЧ рддреНрдпрд╛рдЪреЗ рдХрдкрд╛рдЯ рдереЗрдЯ рд╡рд╛рдЪреВ рд╢рдХрддреЛ рдХрд╛? Data ownership рдЖрдгрд┐ integration.
git checkout lesson-08-data-ownership