فصل ۱۵ — معماری رویدادمحور
مانند Microserviceها، معماری رویدادمحور (Event-Driven Architecture یا EDA) در سیستمهای توزیعشدهٔ مدرن همهجا حضور دارد. بسیاری توصیه میکنند هنگام طراحی سیستمهای Distributed با Coupling کم، مقیاسپذیر و Fault-Tolerant، ارتباط Event-Driven را بهعنوان مکانیزم پیشفرض Integration به کار بگیریم.
Event-Driven Architecture اغلب با DDD مرتبط دانسته میشود. بالاخره EDA بر Eventها استوار است و Eventها در DDD بسیار برجستهاند: Domain Event داریم و در صورت نیاز حتی از Eventها بهعنوان Source of Truth سیستم استفاده میکنیم. ممکن است وسوسه شویم Eventهای DDD را مستقیماً پایهٔ Event-Driven Architecture قرار دهیم. اما آیا این ایدهٔ خوبی است؟
Eventها «سس مخفی» نیستند که روی یک Legacy System بریزید و آن را به یک Distributed System با Coupling پایین تبدیل کنید. دقیقاً برعکس، استفادهٔ بیدقت از EDA میتواند یک Modular Monolith را به Big Ball of Mud توزیعشده تبدیل کند.
در این فصل تعامل EDA و DDD را بررسی میکنیم. Building Blockهای اصلی معماری رویدادمحور، علتهای رایج شکست پروژههای EDA و نحوهٔ استفاده از ابزارهای DDD برای طراحی سیستمهای مؤثر با Integration ناهمزمان را خواهید آموخت.
معماری رویدادمحور
به زبان ساده، Event-Driven Architecture سبکی معماری است که در آن Componentهای یک System با تبادل Event Message بهصورت Asynchronous با یکدیگر ارتباط برقرار میکنند؛ شکل ۱۵-۱ نمونه را نشان میدهد. بهجای فراخوانی Synchronous Endpoint سرویسها، Componentها Event منتشر میکنند تا سایر عناصر سیستم را از تغییرهای دامنه آگاه سازند. Componentهای دیگر میتوانند Subscriber آن Eventها باشند و واکنش نشان دهند. نمونهٔ معمول جریان اجرای Event-Driven همان Saga Pattern است که در فصل ۹ توضیح داده شد.
مهم است تفاوت Event-Driven Architecture و Event Sourcing را برجسته کنیم. در فصل ۷ دیدیم Event Sourcing روشی برای ثبت تغییرهای State به صورت زنجیرهای از Eventها است.
اگرچه هر دو Pattern بر Event تکیه میکنند، از نظر مفهومی متفاوتاند. EDA دربارهٔ ارتباط میان Serviceها است، در حالی که Event Sourcing داخل یک Service رخ میدهد. Eventهایی که برای Event Sourcing طراحی میشوند، State Transitionهای Aggregate در Event-Sourced Domain Model را نمایش میدهند. هدف آنها ثبت ظرافتهای Business Domain است و برای Integration سرویس با سایر Componentهای سیستم طراحی نشدهاند.
در ادامه میبینید سه نوع Event وجود دارد و بعضی از آنها برای Integration مناسبتر از بقیهاند.
Eventها
در سیستم EDA، تبادل Eventها مکانیزم اصلی ارتباط برای Integrate کردن Componentها و تبدیل آنها به یک System واحد است. Eventها را دقیقتر بررسی کنیم و ببینیم چه تفاوتی با Message دارند.
Event، Command و Message
تا اینجا تعریف Event به Message Pattern شبیه است، اما دو مفهوم یکسان نیستند. Event یک Message است، ولی هر Message لزوماً Event نیست. دو نوع Message اصلی داریم:
- Event
- پیامی که تغییری را توصیف میکند که قبلاً رخ داده است.
- Command
- پیامی که عملیاتی را توصیف میکند که باید انجام شود.
Event چیزی است که اتفاق افتاده، در حالی که Command دستور انجام یک کار است. هر دو میتوانند Asynchronous و در قالب Message منتقل شوند. اما Command ممکن است Reject شود: مقصد Command میتواند از اجرای آن خودداری کند؛ برای مثال اگر Command نامعتبر باشد یا با Business Ruleهای سیستم تضاد داشته باشد. گیرندهٔ Event، برعکس، نمیتواند Event را «لغو» کند، چون Event چیزی را شرح میدهد که قبلاً اتفاق افتاده است. تنها راه خنثی کردن اثر یک Event، اجرای Compensating Action—یعنی یک Command—است، همانطور که در Saga Pattern رخ میدهد.
چون Event چیزی را توصیف میکند که قبلاً اتفاق افتاده، نام آن باید در زمان گذشته باشد؛ مانند DeliveryScheduled، ShipmentCompleted یا DeliveryConfirmed.
ساختار Event
Event یک Data Record است که میتوان آن را Serialize و با Messaging Platform انتخابشده منتقل کرد. Schema معمول Event شامل Metadata و Payload است؛ Payload اطلاعاتی است که Event منتقل میکند:
{
"type": "delivery-confirmed",
"event-id": "14101928-4d79-4da6-9486-dbc4837bc612",
"correlation-id": "08011958-6066-4815-8dbe-dee6d9e5ebac",
"delivery-id": "05011927-a328-4860-a106-737b2929db4e",
"timestamp": 1615718833,
"payload": {
"confirmed-by": "17bc9223-bdd6-4382-954d-f1410fd286bd",
"delivery-time": 1615701406
}
}
Payload Event نهتنها اطلاعات منتقلشده را توصیف میکند، بلکه نوع Event را نیز تعیین میکند. اکنون سه نوع Event را دقیقتر بررسی میکنیم.
انواع Event
Eventها را میتوان در سه گروه قرار داد: Event Notification، Event-Carried State Transfer و Domain Event.
Event Notification
Event Notification پیامی دربارهٔ تغییری در Business Domain است که Componentهای دیگر به آن واکنش نشان میدهند. مثالها شامل PaycheckGenerated و CampaignPublished هستند.
Event Notification نباید پرحجم باشد. هدف، اطلاع دادن وقوع Event به طرفهای علاقهمند است، اما Notification نباید همهٔ اطلاعاتی را که Subscriber برای واکنش نیاز دارد حمل کند. برای مثال:
{
"type": "paycheck-generated",
"event-id": "537ec7c2-d1a1-2005-8654-96aee1116b72",
"delivery-id": "05011927-a328-4860-a106-737b2929db4e",
"timestamp": 1615726445,
"payload": {
"employee-id": "456123",
"link": "/paychecks/456123/2021/01"
}
}
کد بالا فقط به Componentهای خارجی اطلاع میدهد یک Paycheck تولید شده است. همهٔ اطلاعات مربوط به Paycheck را حمل نمیکند. Receiver میتواند از Link برای دریافت اطلاعات دقیقتر استفاده کند؛ جریان این Notification در شکل ۱۵-۲ نمایش داده شده است.
از یک منظر، Integration با Event Notification شبیه سیستم Wireless Emergency Alert در ایالات متحده و EU-Alert در اروپا است؛ شکل ۱۵-۳. این سیستمها با Cell Tower پیامهای کوتاه برای هشدار دربارهٔ سلامت عمومی، تهدیدهای ایمنی و وضعیتهای اضطراری Broadcast میکنند. طول Message محدود است؛ بنابراین هشدار برای اطلاعرسانی کافی است، اما برای جزئیات باید به منبع دیگری مراجعه شود.
Event Notification کوتاه در سناریوهای مختلف مفید است. دو مورد مهم:
- Security
- وادار کردن Recipient به Query صریح برای اطلاعات تفصیلی، از انتشار دادهٔ حساس روی Messaging Infrastructure جلوگیری میکند و Subscriber برای دسترسی به داده باید Authorization جداگانه داشته باشد.
- Concurrency
- به دلیل ماهیت Asynchronous Integration، اطلاعات ممکن است تا رسیدن به Subscriber قدیمی شده باشد. اگر داده به Race Condition حساس است، Query صریح امکان گرفتن State بهروز را میدهد. در حالت Consumerهای Concurrent که فقط یکی باید Event را Process کند، Query میتواند با Pessimistic Locking ترکیب شود تا Producer مطمئن شود Consumer دیگری همان Message را پردازش نمیکند.
Event-Carried State Transfer
Event-Carried State Transfer یا ECST، Subscriberها را از تغییر در State داخلی Producer آگاه میکند. برخلاف Event Notification، ECST همهٔ دادهای را که تغییر State را منعکس میکند در Message حمل میکند.
ECST میتواند دو شکل داشته باشد. شکل اول Snapshot کامل State Entity تغییرکرده است:
{
"type": "customer-updated",
"event-id": "6b7ce6c6-8587-4e4f-924a-cec028000ce6",
"customer-id": "01b18d56-b79a-4873-ac99-3d9f767dbe61",
"timestamp": 1615728520,
"payload": {
"first-name": "Carolyn",
"last-name": "Hayes",
"phone": "555-1022",
"status": "follow-up-set",
"follow-up-date": "2021/05/08",
"birthday": "1982/04/05",
"version": 7
}
}
این ECST Snapshot کامل State بهروزشدهٔ Customer را در اختیار مصرفکننده قرار میدهد. برای Data Structureهای بزرگ ممکن است منطقی باشد فقط Fieldهایی که واقعاً تغییر کردهاند در Message قرار گیرند:
{
"type": "customer-updated",
"event-id": "6b7ce6c6-8587-4e4f-924a-cec028000ce6",
"customer-id": "01b18d56-b79a-4873-ac99-3d9f767dbe61",
"timestamp": 1615728520,
"payload": {
"status": "follow-up-set",
"follow-up-date": "2021/05/10",
"version": 8
}
}
چه ECST Snapshot کامل باشد و چه فقط Fieldهای تغییرکرده را حمل کند، Stream این Eventها به Consumer اجازه میدهد Cache محلی State Entityها را نگه دارد و با آن کار کند. از نظر مفهومی، ECST مکانیزمی برای Replication ناهمزمان داده است.
این رویکرد System را Fault-Tolerantتر میکند، زیرا Consumer حتی اگر Producer موقتاً در دسترس نباشد میتواند با Cache محلی به کار ادامه دهد. همچنین Performance Componentهایی را که باید داده را از چند Source پردازش کنند بهبود میدهد؛ بهجای Query کردن همهٔ Sourceها در هر بار نیاز، داده بهصورت Local Cache نگهداری میشود. شکل ۱۵-۴ نمونهای از این الگو در Backend for Frontend را نشان میدهد.
Domain Event
نوع سوم Event Message همان Domain Event است که در فصل ۶ دیدیم. Domain Event از جهتی میان Event Notification و ECST قرار میگیرد: مانند Notification یک رخداد معنادار در Business Domain را توصیف میکند و مانند ECST همهٔ دادهٔ لازم برای توصیف همان رخداد را در خود دارد. با وجود شباهت، این Messageها از نظر مفهومی متفاوتاند.
Domain Event در برابر Event Notification
هر دو تغییر در Business Domain Producer را توصیف میکنند، اما دو تفاوت مفهومی مهم دارند.
نخست، Domain Event همهٔ اطلاعات لازم برای توصیف Event را در خود دارد. Consumer برای داشتن تصویر کامل لازم نیست Action دیگری انجام دهد.
دوم، Modeling Intent متفاوت است. Event Notification با هدف آسانتر کردن Integration با Componentهای دیگر طراحی میشود. Domain Event برای مدلسازی و توصیف خود Business Domain است. Domain Event حتی اگر هیچ Consumer خارجی به آن علاقه نداشته باشد ارزش دارد. این موضوع مخصوصاً در Event-Sourced System مهم است، جایی که Domain Event برای مدلسازی همهٔ State Transitionهای ممکن استفاده میشود. اگر Consumerهای خارجی به همهٔ Domain Eventها Subscribe شوند، طراحی نامناسبی شکل میگیرد؛ بعدتر علت آن را بررسی میکنیم.
Domain Event در برابر Event-Carried State Transfer
دادهٔ داخل Domain Event از نظر مفهومی با Schema یک ECST معمولی فرق دارد.
ECST باید اطلاعات کافی برای نگهداری Local Cache از دادهٔ Producer ارائه کند. هیچ Domain Event منفردی قرار نیست چنین Model غنیای Expose کند. حتی دادهٔ یک Domain Event مشخص نیز برای Cache کردن State Aggregate کافی نیست، زیرا Domain Eventهای دیگری که Consumer Subscriber آنها نیست ممکن است همان Fieldها را تغییر دهند.
علاوه بر این، Modeling Intent متفاوت است. دادهٔ ECST برای توصیف State Aggregate طراحی میشود، اما Domain Event یک رخداد تجاری را در چرخهٔ عمر Aggregate توصیف میکند.
مثال سه نوع Event
برای نشان دادن تفاوت، سه شیوهٔ نمایش رخداد ازدواج را در نظر بگیرید:
eventNotification = {
"type": "marriage-recorded",
"person-id": "01b9a761",
"payload": {
"person-id": "126a7b61",
"details": "/01b9a761/marriage-data"
}
};
ecst = {
"type": "personal-details-changed",
"person-id": "01b9a761",
"payload": {
"new-last-name": "Williams"
}
};
domainEvent = {
"type": "married",
"person-id": "01b9a761",
"payload": {
"person-id": "126a7b61",
"assumed-partner-last-name": true
}
};
marriage-recorded یک Event Notification است. جز اینکه شخص با ID مشخص ازدواج کرده اطلاعات دیگری ندارد. Consumer برای جزئیات باید Link موجود در details را دنبال کند.
personal-details-changed یک ECST است. تغییر در اطلاعات شخص را توصیف میکند: نام خانوادگی تغییر کرده است، اما دلیل را نمیگوید؛ آیا ازدواج رخ داده یا طلاق؟
married یک Domain Event است. تا جای ممکن نزدیک به ماهیت رخداد در Business Domain مدل شده و ID شخص و Flag مربوط به پذیرفتن نام خانوادگی Partner را حمل میکند.
طراحی Integration رویدادمحور
همانطور که در فصل ۳ گفتیم، Software Design عمدتاً دربارهٔ Boundaryها است. Boundary تعیین میکند چه چیزی داخل است، چه چیزی بیرون میماند و مهمتر از همه، چه چیزی از Boundary عبور میکند؛ یعنی Componentها چگونه Integrate میشوند.
Eventها در EDA عناصر درجهیک طراحیاند و هم نحوهٔ Integration Componentها و هم Boundary خود Componentها را تحت تأثیر قرار میدهند. انتخاب نوع درست Event Message میتواند Distributed System را Decouple کند یا برعکس آن را شدیداً Coupled سازد.
پیش از ارائهٔ Heuristicهای انتخاب Event، ببینیم چگونه میتوان با Eventها یک Big Ball of Mud توزیعشده و Strongly Coupled طراحی کرد.
Big Ball of Mud توزیعشده
System شکل ۱۵-۵ را در نظر بگیرید. Bounded Context مربوط به CRM با Event-Sourced Domain Model پیادهسازی شده است. وقتی CRM باید با Marketing Bounded Context Integrate شود، تیمها تصمیم میگیرند از انعطاف Event-Sourced Data Model استفاده کنند و Consumer—Marketing—را Subscriber همهٔ Domain Eventهای CRM کنند تا Model مورد نیاز خود را Project کند.
وقتی AdsOptimization Bounded Context اضافه شد، آن هم باید اطلاعات CRM را Process میکرد. دوباره همان تصمیم گرفته شد: AdsOptimization به همهٔ Domain Eventهای CRM Subscribe کند و Model مناسب خودش را Project کند.
جالب اینکه Marketing و AdsOptimization هر دو لازم داشتند اطلاعات Customer را با Form یکسان نمایش دهند و در نتیجه از Domain Eventهای CRM دقیقاً همان Model را Project کردند: Snapshot تخت از State هر Customer.
Reporting Bounded Context فقط به زیرمجموعهای از Domain Eventهای CRM Subscribe بود. از آنها بهعنوان Event Notification استفاده میکرد تا محاسبات AdsOptimization را Fetch کند. اما چون AdsOptimization نیز با همان Eventها Trigger میشد، برای اطمینان از اینکه Model گزارش بعد از محاسبات Update میشود، Reporting پنج دقیقه پس از دریافت Message آن را Process میکرد.
این طراحی بسیار بد است. انواع Coupling را بررسی کنیم.
Temporal Coupling
AdsOptimization و Reporting از نظر زمانی Coupled هستند: به ترتیب اجرای سختی وابستهاند. AdsOptimization باید قبل از Trigger شدن Reporting پردازش را تمام کند؛ اگر ترتیب برعکس شود، دادهٔ Reporting ناسازگار خواهد شد.
مهندسان برای تحمیل این ترتیب Delay پنجدقیقهای به Reporting اضافه کردهاند تا AdsOptimization زمان کافی برای محاسبه داشته باشد. واضح است که این Delay تضمین نمیکند ترتیب همیشه درست باشد:
- AdsOptimization ممکن است Overload شود و در پنج دقیقه کار را تمام نکند.
- مشکل Network ممکن است تحویل Message به AdsOptimization را به تأخیر بیندازد.
- AdsOptimization ممکن است Outage داشته باشد و Processing Message را متوقف کند.
Functional Coupling
Marketing و AdsOptimization هر دو به Domain Eventهای CRM Subscribe شدهاند و همان Projection از دادهٔ Customer را پیاده کردهاند. یعنی Business Logic تبدیل Domain Event ورودی به State-Based Representation در هر دو Context تکرار شده و دلیل تغییر آن نیز یکسان است: هر دو باید دادهٔ Customer را با Format یکسان نمایش دهند.
در نتیجه اگر Projection در یکی تغییر کند، همان تغییر باید در Context دوم نیز اعمال شود. این Functional Coupling است: چند Component همان Business Functionality را پیاده میکنند و با تغییر آن باید همزمان تغییر کنند.
Implementation Coupling
این نوع Coupling ظریفتر است. Marketing و AdsOptimization به همهٔ Domain Eventهای Event-Sourced Model CRM Subscribe کردهاند. در نتیجه، یک تغییر در Implementation CRM—مثلاً اضافه شدن Domain Event جدید یا تغییر Schema Event موجود—باید در هر دو Subscriber نیز منعکس شود. در غیر این صورت ناسازگاری داده ممکن است ایجاد شود.
اگر Schema Event تغییر کند، Projection Logic Subscriberها Fail میشود. اگر Domain Event جدیدی به Model CRM اضافه شود، ممکن است روی Model Projectشده اثر بگذارد؛ نادیده گرفتن آن میتواند State ناسازگار تولید کند.
بازآرایی Integration رویدادمحور
همانطور که میبینید، «ریختن Event روی سیستم» آن را Decoupled یا Resilient نمیکند. ممکن است این مثال غیرواقعی به نظر برسد، اما نویسنده میگوید بر اساس یک داستان واقعی است. ببینیم چگونه میتوان Eventها را تغییر داد و طراحی را بهطور چشمگیری بهتر کرد.
Expose کردن همهٔ Domain Eventهای Data Model CRM، Subscriberها را به جزئیات Implementation Producer Coupled میکند. برای رفع Implementation Coupling باید مجموعهٔ بسیار محدودتری از Eventها یا نوع متفاوتی از Event را Expose کنیم.
Marketing و AdsOptimization نیز به دلیل پیادهسازی Business Functionality یکسان از نظر Functional Coupling به یکدیگر وابستهاند.
هر دو مشکل را میتوان با Encapsulate کردن Projection Logic در Producer—یعنی CRM Bounded Context—حل کرد. بهجای Expose کردن Implementation Detail، CRM میتواند Consumer-Driven Contract را دنبال کند: Model مورد نیاز Consumerها را Project کند و آن را بخشی از Published Language خود قرار دهد؛ یعنی یک Model مخصوص Integration که از Implementation Model داخلی جدا است. در نتیجه Consumerها همهٔ دادهٔ لازم را میگیرند بدون آنکه از Model داخلی CRM آگاه باشند.
برای رفع Temporal Coupling میان AdsOptimization و Reporting، AdsOptimization میتواند Event Notification منتشر کند و Reporting پس از دریافت آن دادهٔ مورد نیاز را Fetch کند. System بازآراییشده در شکل ۱۵-۶ نشان داده شده است.
Heuristicهای طراحی Event-Driven
همراستا کردن نوع Event با Task مورد نظر، طراحی را چند مرتبه کمتر Coupled، منعطفتر و Fault-Tolerantتر میکند. Heuristicهای پشت تغییرهای بالا را صورتبندی کنیم.
بدترین حالت را فرض کنید
همانطور که Andrew Grove میگوید «فقط پارانوئیدها زنده میمانند». این را اصل راهنمای طراحی سیستمهای Event-Driven قرار دهید:
- Network کند خواهد شد.
- Serverها در بدترین لحظه Fail خواهند شد.
- Eventها Out of Order خواهند رسید.
- Eventها Duplicate خواهند شد.
و البته این اتفاقها احتمالاً در آخر هفته و تعطیلات رسمی بیشتر رخ میدهند.
کلمهٔ Driven در Event-Driven Architecture یعنی کل System به تحویل موفق Messageها وابسته است. پس از ذهنیت «همهچیز درست پیش میرود» دوری کنید. مطمئن شوید Eventها همیشه و حتی در شرایط خطا بهصورت سازگار Deliver میشوند:
- برای Publish قابل اعتماد Messageها از Outbox Pattern استفاده کنید.
- هنگام Publish مطمئن شوید Subscriberها میتوانند Message تکراری را Deduplicate و Messageهای Out-of-Order را شناسایی و دوباره مرتب کنند.
- برای Orchestration فرایندهای Cross-Bounded-Context که به Compensating Action نیاز دارند از Saga و Process Manager استفاده کنید.
Eventهای عمومی و خصوصی داشته باشید
هنگام Publish کردن Domain Event، مخصوصاً در Event-Sourced Aggregate، مراقب Expose کردن جزئیات Implementation باشید. Eventها را بخشی ذاتی از Public Interface Bounded Context بدانید. بنابراین هنگام پیادهسازی Open-Host Service مطمئن شوید Eventها در Published Language زمینه منعکس شدهاند. Patternهای تبدیل Modelهای Event-Based در فصل ۹ بررسی شدهاند.
هنگام طراحی Public Interface Bounded Context از انواع متفاوت Event استفاده کنید. ECST میتواند Implementation Model را به Model جمعوجورتری فشرده کند که فقط اطلاعات مورد نیاز Consumer را منتقل میکند. Event Notification میتواند Public Interface را باز هم کوچکتر کند. Domain Eventها را برای ارتباط با Contextهای خارجی با احتیاط و بهصورت محدود استفاده کنید؛ حتی میتوانید مجموعهای از Public Domain Eventهای اختصاصی طراحی کنید.
Consistency Requirementها را ارزیابی کنید
هنگام طراحی ارتباط Event-Driven، Consistency Requirementهای Bounded Context را Heuristic دیگری برای انتخاب نوع Event قرار دهید:
- اگر Componentها میتوانند با Eventually Consistent Data کار کنند، از Event-Carried State Transfer استفاده کنید.
- اگر Consumer باید آخرین Write موجود در State Producer را بخواند، Event Notification منتشر کنید و سپس با Query، State بهروز Producer را Fetch کنید.
جمعبندی
این فصل Event-Driven Architecture را بهعنوان جنبهای ذاتی از طراحی Public Interface Bounded Context معرفی کرد. سه نوع Event برای ارتباط Cross-Bounded-Context را آموختید:
- Event Notification
- اطلاع میدهد اتفاق مهمی رخ داده، اما Consumer برای اطلاعات بیشتر باید Producer را Query کند.
- Event-Carried State Transfer
- مکانیزمی برای Data Replication مبتنی بر Message. هر Event Snapshotی از State را حمل میکند که میتواند برای نگهداری Cache محلی Producer استفاده شود.
- Domain Event
- Messageای که یک رخداد در Business Domain Producer را توصیف میکند.
استفاده از نوع نامناسب Event میتواند سیستم EDA را از مسیر خارج کند و ناخواسته آن را به Big Ball of Mud تبدیل سازد. برای انتخاب Event مناسب، Consistency Requirementهای Bounded Context را ارزیابی کنید و از Expose کردن Implementation Detail پرهیز کنید. مجموعهٔ صریحی از Public و Private Event طراحی کنید. در نهایت، مطمئن شوید System حتی هنگام مشکل فنی و Outage نیز Messageها را تحویل میدهد.
تمرینها
- کدام عبارت یا عبارتها درستاند؟
- Event-Driven Architecture Eventهایی را تعریف میکند که قرار است از Boundary مؤلفهها عبور کنند.
- Event Sourcing Eventهایی را تعریف میکند که قرار است داخل Boundary Bounded Context باقی بمانند.
- EDA و Event Sourcing نامهای متفاوت یک Pattern هستند.
- A و B درستاند.
- کدام نوع Event برای ارتباط تغییرهای State مناسبتر است؟
- Event Notification
- Event-Carried State Transfer
- Domain Event
- همه به یک اندازه مناسباند.
- کدام Pattern یکپارچهسازی Bounded Context نیازمند تعریف صریح Public Eventها است؟
- Open-Host Service
- Anticorruption Layer
- Shared Kernel
- Conformist
- Serviceهای S1 و S2 بهصورت Asynchronous Integrate شدهاند. S1 باید داده را منتقل کند و S2 باید بتواند آخرین دادهٔ نوشتهشده در S1 را بخواند. کدام Event برای این Integration مناسب است؟
- S2 باید ECST منتشر کند.
- S2 باید Public Event Notification منتشر کند تا S1 را برای یک Request همزمان و دریافت State بهروز Trigger کند.
- S2 باید Domain Event منتشر کند.
- A و B.