DDD, Saga та пошук подій: Чи може компенсувати дію просто видалення з магазину подій?


15

Я усвідомлюю, що вищезазначене запитання, ймовірно, викликає декілька «що ??

Я намагаюся обернути голову на кілька споріднених концепцій, в основному шаблону Saga ( http://www.rgoarchitects.com/Files/SOAPatterns/Saga.pdf ) у поєднанні з джерелом подій (концепція DDD : http://en.wikipedia.org/wiki/Domain-driven_design )

Хороший пост, який обговорює його разом: https://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/

Я переходжу до питання за хвилину, але я думаю, що я повинен спробувати узагальнити те, що я розумію в ньому спочатку (що може бути неправильним, тому, будь ласка, виправте, якщо це так), оскільки це може вплинути на те, чому я задати питання для початку:

  1. Шаблон Saga - це свого роду брокер, який дає дію (кінцевий користувач, автоматизований тощо, по суті, все, що збирається змінити дані), ділить цю дію на ділову діяльність і надсилає кожну з цих дій як повідомлення на шину повідомлень, яка у свою чергу надсилає його до відповідних корінних коренів, про які слід піклуватися.
  2. Ці сукупні корені можуть діяти повністю автономно (приємне роз'єднання проблем, велика масштабованість тощо)
  3. Сам екземпляр Saga не містить жодної логіки бізнесу, яка міститься в сукупних коренях, до яких він надсилає діяльність. Єдина «логіка», що міститься в «Сазі», - «логіка процесу» (часто реалізована як державна машина), яка визначає на основі отриманих дій (а також подальших подій), що робити (тобто: які дії надсилати)
  4. Шаблони Saga реалізують своєрідну схему розподілених транзакцій. Тобто: коли одне з корінних коренів (які знову працюють автономно, не знаючи про існування інших людей) не вдається, всю дію, можливо, доведеться відкрутити назад.
  5. Це реалізується, маючи всі сукупні корені після завершення звіту про свою діяльність до Саги. (У випадку успіху, а також помилки)
  6. У випадку, якщо всі сукупні корені повернуть успіх, внутрішній державний механізм, якщо Сага визначає, що робити далі (або вирішує, що буде зроблено)
  7. У разі невдачі Сага видає всі сукупні корені, які брали участь в останній дії, так звану компенсаційну дію, тобто: дію для скасування останньої дії, зроблене кожним із сукупних коренів.
  8. Це може бути просто "мінус 1 голос", якщо дія була "плюс 1 голос", але це може бути складніше, як відновлення поштового блогу до попередньої версії.
  9. Надання подій (див. Поштовий блог, що поєднує два) має на меті зовнішнє збереження результатів кожної з заходів, які кожен із сукупних коренів здійснює до централізованого магазину подій (зміни в цьому контексті називаються "подіями")
  10. Цей магазин подій є "єдиною версією правди" і може бути використаний для відтворення стану всіх об'єктів, просто повторивши збережені події (фактично як журнал подій)
  11. Поєднання двох (тобто: дозволити сукупним кореням використовувати джерело подій для аутсорсингу, зберігаючи свої зміни, перш ніж звітувати назад у Сагу) дає безліч приємних можливостей, одна з яких стосується мого питання ...

Я відчував, що мені потрібно зірвати це з плеча, адже це багато чого можна зрозуміти за один раз. Враховуючи цей контекст / умонастрій (ще раз, виправте, якщо не так)

питання: Коли сукупний корінь отримує Компенсаційну дію і якщо цей сукупний корінь переклав зовнішні зміни, зміни станів використовуються як джерело подій, чи не буде Компенсаційна дія в усіх ситуаціях просто видаленням останньої події в Магазині подій для цього дано сукупний корінь? (Припустимо, що реалізація зберігається дозволяє видаляти)

Це мало б для мене сенсу (і це було б ще однією великою перевагою цієї комбінації), але, як я вже сказав, я можу робити ці припущення на основі неправильного / неповного розуміння цих понять.

Я сподіваюся, що це не стало занадто довго.

Спасибі.

Відповіді:


9

Не слід видаляти події зі свого магазину подій. Вони являють собою щось, що сталося. Якщо щось трапиться зараз, то і ви повинні це знати, тому додайте подію, яка змусить ваш агрегат повернутися до якогось попереднього стану. Шкода видалити інформацію зі своєї бази даних.

подумайте на прикладі візка з greg young та вилучених предметів. Завтра може бути інформація про компенсаційну дію може мати будь-яку цінність.

Щодо саги, то кожна річ правильна, наскільки я сам знаю. Вам слід думати про сагу як про державну машину. Це робить тільки це.

Це команда, яку видає сага, щоб сказати сукупності щось робити. З цієї дії відбудеться подія. Ця подія може бути коригувальною дією, яка вам потрібна, або може бути денормалізованою, щоб якийсь користувач побачив її, щоб вирішити, що робити.

Це залежить від правил вашого бізнесу. У цьому випадку є легке виправлення: сукупний корінь знає, що в такому випадку ви це робите, або вибір занадто складний, щоб зробити це програмно (вартість розробки занадто висока), і тому ви можете запропонувати це якомусь користувачеві, який може вибирати між різними діями. Все залежить від контексту дії, що компенсує. Це чисті ділові правила. Що ми маємо робити в цьому чи іншому випадку. Це щось запитати у вашого експерта з домену, а потім вибирати разом з ним, якщо краще розробити автоматичне рішення або якщо рішення - запитати користувача Рональда Р., оскільки він зазвичай відповідає на це запитання.


Як сукупність дізнається, до якої держави повернутись? Чи буде дозволено запитувати проти магазину подій чи чогось іншого?
Geert-Jan

Він не повинен повертатись, але додати іншу подію. Це команда, яку видає сага, щоб сказати сукупності щось робити. З цієї дії відбудеться подія.
Артіс

Так, я розумію. "Повернення", ймовірно, було обрано неправильно. Розглянемо наступне: я б хотів використовувати Sourcing подій з Sagas для моделювання, серед іншого, потоків публікації / затвердження документів. Що робити, якщо редактор надіслав дію ChangeBlogBody, яка в кінцевому рахунку зберігається як подія BlogBodyChanged в магазин подій. Опісля чомусь видається Компенсаційна акція. Звідки Агрегат дізнається, яка компенсує подія, яка спричинить за собою зміст органу блогу, як це було безпосередньо перед випуском дії ChangeBlogBody?
Geert-Jan

Це залежить від правил вашого бізнесу. У будь-якому випадку, є легке виправлення: сукупний корінь знає, що в такому випадку ви це робите, або вибір занадто складний, щоб зробити це програмно (вартість розробки занадто висока), і тому ви можете запропонувати це якомусь користувачеві, який Ви можете вибрати між різними діями.
Артіс

Все залежить від контексту дії, що компенсує. Це чисті ділові правила. Що ми маємо робити в цьому чи іншому випадку. Це щось запитати у вашого експерта з домену, а потім вибирати разом з ним, якщо краще розробити автоматичне рішення або якщо рішення - запитати користувача Рональда Р., оскільки він зазвичай відповідає на це запитання.
Артіс

6

Для повноти я подумав включити відповідний фрагмент від Мартіна Фаулера про способи повернення стану:

Окрім подій, що грають самі вперед, їм також часто корисно мати можливість змінити перелом.

Поворот є найпростішим, коли подія подається у формі різниці. Прикладом цього може бути "додати $ 10 на рахунок Мартіна" на відміну від "встановити рахунок Мартіна в $ 110". У першому випадку я можу повернути, віднімаючи лише 10 доларів, але в другому випадку у мене недостатньо інформації, щоб відтворити минулу вартість рахунку.

Якщо вхідні події не дотримуються різницького підходу, то подія має забезпечити, щоб вона зберігала все, що потрібно для реверсування під час обробки. Це можна зробити, зберігаючи попередні значення на будь-якому зміненому значенні або обчислюючи та зберігаючи різниці в події.

Від: http://martinfowler.com/eaaDev/EventSourcing.html


1

Концептуально:

  • Подія - це те, що сталося. Минуле не можна змінити.
  • Команда - це щось робити. Команда може не відбутися (може бути відхилена).

Ми можемо змінити наш майбутній стан лише виконавши іншу команду (Компенсувати дію), яка повинна призвести до зміни стану події програми.

Щоб "зняти з пантелику" питання, подумайте про цю фразу "видалити останню подію":

  • Що робити, якщо остання подія не є тією, яку потрібно видалити? Що робити, якщо після видалення відбулися інші події? Ці події теж потрібно змінити (як їх базовий стан змінився б, видаливши перед ними подію).
  • Що робити, якщо подія була надіслана до зовнішньої системи? У вас може бути доступ до виправлення його стану, окрім надсилання іншої події.

Коротше кажучи, у вас немає можливості видалити події в межах CQRS.

Ви можете зменшити свій магазин подій, зробивши стан знімків (який базується на всіх подіях, що ведуть до цього стану), але цей фізичний аспект не має нічого спільного з концепцією події.


0

Ґерт-Ян, я теж думаю, що компенсаційна дія може просто видалити відповідну подію. Це має сенс, і це показує ще одну перевагу дизайну подій Sourcing.

Деякі кажуть, що видалення події порушує "принципи" пошуку подій або CQRS. Я думаю, що це обмежувальне узагальнення. Я думаю, що нормально видалити подію, якщо вона створена в межах глобальної транзакції, яка скасовується. Розглянемо псевдокод:

try {
    newEvents = processMycommand(myCommand)
    for (Event newEvent : newEvents)
        EventStore.insertEvent(newEvent);
} catch (Exception e) {
    EventStore.rollback();
}

Припустимо, ваш магазин подій є транзакційною базою даних. У псевдокоді ви можете уявити ситуацію, коли ви вставили першу подію, але при спробі вставити другу подію було викинуто виняток. Команда відкату природно поверне вставку першої події. Це розумно?

Якщо це розумно для транзакції бази даних ACID (транзакції з фіксацією / відкатом), чому б це не було розумним для компенсації транзакції?

Виконуючи глобальну транзакцію Saga, зміни даних можна скасувати (за рахунок компенсації). Не потрібно зберігати подію, створену під час транзакції, оскільки транзакція не завершилася.

Тепер, якщо компенсація намагається видалити подію і ця подія не є новітньою подією на об'єкті, видалення не повинно відбуватися. Але в цілому, це навряд чи станеться, особливо в рішеннях, що інтенсивно читають.


0

Давайте пограємо з думкою, що сховище подій - це лише дані, які ви хочете зберегти. Наприклад, у нас може бути жорсткий диск, ми можемо почати спочатку і записувати на нього дані. Кожен раз, коли ми отримуємо подію, ми додаємо свої попередні дані, тому ми просто продовжуємо писати на диску, де ми зупинилися востаннє. Коли ми хочемо видалити подію, ми повертаємося назад, виймаємо цю частину з диска і залишаємо пробіл. Повернення самостійно уповільнює наше зберігання подій, але ми можемо з цим жити. Якщо ми використовуємо файлову систему, це спробує заповнити прогалину останніми подіями, тож у нас з’явиться повільне фрагментарне сховище або ми можемо дефрагментацію. Жоден із них - це те, що нам не подобається. Якщо ми говоримо про бази даних, ви отримуєте це, якщо ви використовуєте реляційну базу даних замість додавання лише бази даних для зберігання ваших подій:

введіть тут опис зображення посилання: https://cambridge-intelligence.com/bringing-time-series-data-to-life-with-keylines/

Ofc. для звичайного сайту це не має значення, але ці рішення розроблені для величезних веб-сайтів, таких як facebook, google тощо. Тому справді питання не має сенсу, адже як би ви видалили подію в базі даних, що додається, і як би ви називаєте компенсацію чимось на зразок побудови машини часу та повернення назад у часі, щоб змінити чи запобігти події ???

Афаїк. єдиний спосіб вирішити це - створити нове сховище для подій, де ви виключаєте події, яких ви не хочете мати, і після цього видаляєте старе сховище подій. Але це екстремальне рішення, щоб зняти одну подію. Якщо ми говоримо про GDPR, то єдиним відомим хорошим рішенням є зберігання особистих даних, зашифрованих у сховищі подій, та видалення ключа шифрування з іншої бази даних.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.