Владение данными и состоянием — Примеры

Пример 1 — Два сервиса пишут в одну таблицу

Сервис заказов и сервис отчётов обновляют одну таблицу, и цифра, исправленная одним, молча перезаписывается другим. Найдите нарушенное правило владения, затем решите, кто пишет.

orders(total, status)          одна общая схема

сервис заказов:  вставляет заказы, обновляет статус
сервис отчётов:  обновляет total, когда исправляет цифру

на прошлой неделе: ночная синхронизация заказов дважды перезаписала исправление

Решение

владелец: сервис заказов   единственный писатель; инварианты живут здесь
читатель: сервис отчётов   держит собственную модель чтения, заказы не пишет

сервис заказов --событие--> сервис отчётов --проектор--> reporting.orders_view

С одним писателем правила о том, какой может быть сумма заказа, существуют ровно в одном месте, а об остальном можно рассуждать как о потребителе. Два писателя превращают каждый инвариант в договорённость между командами — чем перезаписанное исправление и было. Копии читателя позволено отставать, но менять источник она не вправе. Если сервису отчётов действительно нужна собственная исправленная цифра, ей место в его модели чтения, помеченной как производная и пересобираемая, а не в таблице владельца.

Пример 2 — Чтение, противоречащее только что сделанной записи

Пользователь переименовывает проект, запись проходит успешно, а следующая страница всё ещё показывает старое имя: объясните, какое окно это вызвало, и выберите, что должно делать чтение.

запись  -> владелец проектов (зафиксирована)
чтение  -> модель чтения поиска (построена минутами раньше)
итог    -> переименования там ещё нет

Решение

// чтения, которым нужна свежесть, идут к владельцу
const project = await projects.get(id);

// чтения, терпящие запаздывание, используют копию, и это сказано в одном месте
const results = await search.query(term);          // «достаточно свежего» здесь хватает

Как только копия существует, она устаревает с момента создания, и проектный вопрос не в том, происходит ли это, а в том, что система делает во время окна. Сформулируйте требование: переименование, которое пользователь только что сделал, должно быть видно ему самому, а поисковый индекс, отстающий на секунду-две, вполне приемлем. Тогда чтения распадаются на два пути вместо одного расплывчатого, а класс запутанных сообщений превращается в задокументированное свойство с местом для номеров версий, повторных попыток или маршрута чтения собственных записей.