Тут на форуме уже и желающие были так свой доход перечислять — «сложна бухалтерию считать, не могу собрать выписки со всех своих одного аккаунта и умножить на пять процентов. Даёшь автоматизацию в кабинете налогоплательщика»
Пацаны расходимся, мы не так всё поняли, поскольку не ту версию закона ревьювили. Релиз зафиксирован, коммиты больше не принимаются. Все необходимые заказчику хотфиксы будут добавлены на прод в момент заливки.
В посиланнях є LinkedIn автора — запитуйте там. У мене лише припущення, що якийсь параметр файлової системи не влаштовує — або пошук файла довше, або швидкість послідовного читання, або кількість файлів/нод обмежена.
Я бы с ходу выбирал что-то серилизуемое и сжимаемое.
Можно и json+zip, можно protofuf+zip, messagepack+zip.
Хранить меньше, передавать быстрее. Если девелоперы на фронте и беке умеют — делайте. На анализ много времени главное не тратьте — нет так нет, да — берем то с чем работали — вы не убер ;)
eng.uber.com/...son-encoding-compression
по другой версии там так же руби пробегал на бек-енде.
news.ycombinator.com/item?id=23047495
Our front-end tech stack: TypeScript, React, C++, WebAssembly, WebGL
Our back-end tech stack: Ruby, Sinatra, Go, Rust
Є дуже змістовне поясненя — „Я великий фан принціпу Тримай його простим, дурню”! :)
One of things people are most shocked to learn about Figma’s infrastructure is that it’s backed by a single database instance running on one of the beefiest machine in AWS. Surprising, right? We are a big fan of the KISS design principle and this simple approach has gotten us pretty far.
А у Шустера уже были? Как аудитория реагирует на предложение?
Лучший проект в этом классе — figma.
Но там самое основное — frontend, написанный на С++ и компилируемый в WASM с использованием WebGL. Писался «подорванным» основателем — программистом.
В первых версиях все грузилось из одного файла, который апдейтился последовательностью CDRT операций одним экземпляром процесса на каждый такой файл (www.figma.com/...iplayer-technology-works).
Бек-энд в первой версии typescript, потом переписывался на Rust.
База данных — на одной вертикально-масштабируемой машинке AWS с монго памяти и монго процесором (я надеюсь я установил раппорт с вашим подсознанием ;)).
На такой машинке и взлетели и жили долго и счастливо, пока не пришли большие компании с корпоративными хотелками (www.figma.com/...of-figmas-infrastructure)
Сейчас только перешли к усложнению и думают оверинжинерить, надеюсь ничего не поломают...
Ни одного недовольного разруливанием не обнаружено :)
youtube.com/watch?v=AqNdKtahx58?t=111
А налоговой киевских районов по контракту и с конвертами/чемоданами?
По редактированию пока писать статью с примерами не готов, по-этому воспользуюсь подсказкой зала и кину ссылку на статью с одной из возможных реализаций flpvsk.com/...irst-apps-event-sourcing и на github со второй реализацией github.com/...vent-sourcing-application
PS. в обоих случаях вместо команд используют эвенты, но это не эвенты доменной модели, скорее это протокол мапинга комманд и представления read-model. Иcпользовать там доменные ивенты врагу не пожелаю.
Ок, на примере заказа в офлайне.
Пользователь заполняет поля в интерфейсе. Поскольку скорее всего это будут новые агрегаты, то для них создаются комманды создания агрегата с новым id, комманды создания и обновления вложенных entity (со своими уникальными id). Набор комманд применяется к UI упаковываем в батч и ставим в локальную очередь. Батч на сервере применяем целиком — сохраняем события в ленту в рамках внешнего unit of work. Вложенные и генерируемые интерсепторами комманды могут работать в пределах units of work интерсепторов со своими стратегиями сохранения. Для новых агрегатов до отправки версии не определены. После отправки батча для каждого id агрегата получаем ответ с новыми версиями и ошибками валидации.
Если пользователь на странице — применяем ответ — обновляем клиентские версии, подсвечиваем ошибки.
Если ушел — зависимости от задачи можем просто показать глобальным обработчиком ошибку, либо в коде viewModel блока или страницы в методе onCommit создать подписку на ошибки конкретных агрегатов и обрабатывать их (например, в попапе предлагаем вернуться на страницу и при загрузке view model применяем команды к начальному состоянию, обновляем интерфейс и показываем ошибки).
Редактирование уже отправленных данных — это уже другие задачи :)
Amazon RDS c плоскими таблицами и серелизацией евентов, база слоится по хешам клиентов, областям, агрегатам.
Архитектура повторяет структуру комманды разработки — монолит с хорошими контекстами по предметным областям и feature switch.
Простейшая конкурентная модель просто следит за порядком версий команд на back-end и отфутболивает неверные. Сложнее — мерджинг стратегии.
На клиенте используем model-view-update или mvvm с полноценной объектной моделью и команды применяются к модели меняя ее состояние.
Часть полей данных в модели имеет two-phase состояние с origin и current значениями и их версиями и обрабатывают two-phase commit protocol для обновления. Могут быть вложенные поля, тогда методы протокола просто делегируются всем детям по цепочке вложенности.
Уведолления о обновлениях приходят по web-socket как список вида readmodel;version;[list of ids] по которому подписавшиеся модели запрашивают обновлённые данные.
Единственное но — нет единого шаблона на все случаи. Каждый тип интерфейсов может использовать или блокировки или мержинг или комбинировать. Много rxjs для апдейтов моделей в определенном порядке, уменьшения числа запросов
Динамика — большая часть приложения может работать на неустойчивых каналах связи или параллельно (в зависимости от задачи). Соответственно, там где важен оффлайн команды кидаются в очередь на отправку и сразу применяются на UI, там где важнее взаимодействие и канал стабилен(часто офисные задачи) — команды отстреливают с конфликтами. В обоих вариантах web интерфейс слушает апдейты read-model и обновляет состояние сопоставляя его с текущим. Без ES на порядок сложнее поддерживать оба юзкейса.
Тестирование упрощается — вместо юнит тестов тестируются события, генерируемые на определенный набор команд, при пустой или фиксированной истории событий. Иногда при возникновении пограничных багов делается просто слепок истории событий до момента ошибки и фиксируется результат ошибки или требуемый результат как тест на баг-как-фича. Прогон таких тестов перед релизами помогает понять что исправлено, и что нужно доносить клиентам. (Например, клиент очень хочет менять начисление зарплат после отчетного периода — мы говорим что нет, и отправляем на сайт налоговой. А оставленный тест спасает от настырного клиента который хочет решить туже задачу поменяв логику взаимодействия внутри агрегата под другим соусом).
Ну и работа с данными — все read-model билдятся динамически. Из одного потока событий можно создавать множество проекций, при этом оставляя старые и отдавая новые только ограниченному числу клиентов для канареечного теста новых фич.
Агрегаты меняются постоянно с разрастанием функционала, но это не сложная задача и шариться в команде на примерах «хороших» кейсов. О read-model вообще не парились — если кто-то просадил перфоманс — в мониторинге время отклика покажет и это только один билдер который можно изолировать и написать несколько proof of concept для решения задачи.
А вот сами эвенты — это хранители всех ошибок и неверных решений — на каждый агрегат может появится папка deprecated в которой хранятся все обработчики и контракты неверно спроектированных эвентов, которые создавать больше нельзя, но обработать обязан.
Когда не нужно использовать CQRS (помимо указанных накладных расходов на поддержку инфраструктуры) — когда в задаче нет бизнес процессов с ограничениями на стороне wrtite-model (обработка статистики, загрузка и обработка batch data files, ввод данных без необходимости аудита, сложных кросс валидаций или realtime collaboration)
Audit trail получаете из коробки, все действия фиксированы, но в случае PCI DSS и GDPR вместо пайлоада часто хранятся хеши, id данных на внешних железках или кодированые данные.
По требованиям к масштабируемости и сложности могу привести два примера:
— процессинг с 15 млн карточных транзакций в месяц привязанных к акционным, бонусным и плюшечным бизнес программам. Частота смены логики програм по тысячам партнеров — в среднем раз в полгода-квартал. 5 dev, 3 тестировщика, 2 года c 99.95% availability.
— нишевая SAAS ERP с поддержкой таких областей как: управление производством (шедулинг и алокейшен ресурсов, мониторинг линий, отчеты и поддержка основных операций); бухгалтерия; персонал (зарплаты, отпуска, выходные, бонусы, больничные); продажи (расчет предложений, встречи, контакты, букинги, SMS/chat/email коммуникации, инвойсы); сервис (расписания, рабочие ордера); логистика (поставщики, экспедиторы, склад); 300+ скринов, 1200+ read-models, 150+ агрегатов. 5 девов/2 тестировщика, 3 года бесперебойной работы
Адовые задачи, некоторые усложнения из complicated области. Выбирайте решения исходя из требований. Реализации могут быть очень простыми и очевидными. Всякие конфигурации делегатами и худами в фреймворках сейчас не кажуться никому сложными.
Занят зайка