Data engineering
Event sourcing: построй аудируемый ledger
Читать про event sourcing это не то же, что жить с append-only логом. Построй маленький ledger, где лог это единственный источник истины, выведи каждое чтение из него, потом докажи свойства, ради которых паттерн стоит своей цены — темпоральный запрос, пересборку projection, ускорение через snapshot, эволюцию схемы и стирание по GDPR — каждое с доказательством.
Преврати ментальную модель юнита в работающую систему: append-only хранилище событий с оптимистичной конкурентностью, одноразовую CQRS read-модель, темпоральные запросы через replay, snapshot, ограничивающие стоимость загрузки, upcaster для эволюционировавшего события и crypto-shredding для стирания — продемонстрировано, а не заявлено.
Построй маленький event-sourced сервис ledger счетов (любой язык), где append-only лог событий это единственный источник истины, все чтения это производные projection, и ты можешь продемонстрировать на нём аудит, темпоральный запрос, пересборку, snapshot, версионирование и стирание по GDPR.
- Тест конкурентности: два append на одной ожидаемой версии, один успешен, один падает с ошибкой конфликта версий — никогда потерянного обновления или молча смерженной записи.
- Тест идемпотентности: достань то же событие в projection дважды и покажи, что read-модель идентична одиночной доставке (checkpoint блокирует повторную доставку).
- Доказательство пересборки: удали read-модель балансов, проиграй и покажи побайтово те же балансы; плюс вторую projection, произведённую исключительно из проигранной истории.
- Результат темпорального запроса, совпадающий с вручную вычисленным балансом на момент, и бенчмарк snapshot: время загрузки длинного потока со snapshot против полного replay, с приведёнными числами.
- Тест upcaster: сохранённое событие до изменения загружается и сворачивается корректно через текущий путь кода, а сохранённое на диске событие показано неизменным.
- Доказательство crypto-shredding: до forget имя расшифровывается; после уничтожения ключа replay всё ещё пересобирает все балансы, пока имя навсегда невосстановимо. Отметь письменно юридическую оговорку, что регуляторы могут всё ещё считать неудаляемую зашифрованную PII персональными данными.
- Добавь read-your-own-writes для экрана после команды: возвращай состояние из результата команды, чтобы UI не показывал отстающую projection, и продемонстрируй, что лаг eventual consistency невидим пользователю.
- Сделай projection отдельным процессом, потребляющим поток асинхронно, замерь лаг read-модели под нагрузкой и покажи, что read-модель сходится после прекращения всплеска записей.
- Добавь второй бэкенд хранилища событий (например, поменяй SQL-таблицу на топик Kafka) и задокументируй, что придётся изменить — бесконечный retention, без компакции, и как воспроизвести конкурентность по ожидаемой версии, которой в Kafka нет нативно.
- Добавь endpoint аудита, отвечающий на «кто менял план в дату X и каким было прежнее значение» чисто из лога, демонстрируя аудит-трейл и темпоральный запрос, нужные для сценария спора с клиентом из урока.
Это цикл, который гоняет любая event-sourced система: добавляй неизменяемые события с оптимистичной конкурентностью как единственный источник истины, сворачивай их для загрузки агрегатов и валидации команд, выводи одноразовые идемпотентные projection для чтений и отвечай на темпоральные запросы свёрткой до timestamp. Потом защищай цену — snapshot, чтобы ограничить replay (с контрольной суммой против дрейфа), upcaster, чтобы эволюционировать схемы без переписывания истории, и crypto-shredding, чтобы удовлетворить GDPR поверх неизменяемого лога. Построй это однажды на игрушечном ledger, и продакшен-версия — споры по аудиту, новые read-модели через месяцы, эволюция схемы под нагрузкой — станет знакомой формой, а не прыжком веры.