Перейти к основному содержимому

@hlf-explorer/monitor

@hlf-explorer/monitor — это переиспользуемая библиотека, которую встраивают прикладные приложения, когда им нужно реагировать на то, что происходит в ledger. Здесь есть тонкость, которую лучше уловить сразу, чтобы потом не путаться: monitor не ходит в Fabric напрямую. Он слушает API самого эксплорера, а backend эксплорера уже наполнил базу сырыми блоками. Иными словами, backend отвечает за сырьё, а monitor извлекает из него прикладной смысл.

Движок отслеживания — LedgerMonitor. Он подключается к ledger по сокету, по таймеру сверяет высоту с сохранённой и на новые блоки ставит задачу разбора. При старте он ещё и добирает пропущенные блоки, так что ни один блок не выпадет из обработки, даже если приложение какое-то время лежало.

Самое интересное начинается в обработчике разбора — LedgerBlockParseHandler. Он держит реестр парсеров по именам событий chaincode и в одной транзакции базы проходит по всем событиям блока, отдавая каждое своему парсеру. А парсер — это LedgerEventParser, и именно его наследует прикладной код, описывая, что делать с конкретным бизнес-событием. Внутри парсер складывает результат в четыре корзины, и это деление принципиально:

  1. entities — прикладные сущности, которые сохраняются тут же, внутри той же транзакции.
  2. events — доменные события, которые рассылаются сразу после коммита, локально.
  3. socketEvents — события, которые уходят клиентам по сокету.
  4. commands — действия, которые парсер не может выполнить сам внутри транзакции, и которые отправляются другим сервисам приложения уже после коммита.

На этом разделении стоит задержаться, потому что именно с ним связано честное ограничение, о котором мы пишем прямо. Сущности сохраняются атомарно вместе с самим фактом «блок разобран», а вот команды отправляются после коммита и без ожидания результата. Значит, если процесс упал между коммитом и рассылкой, команда теряется: база помнит, что блок разобран, а действие, которое должно было за ним последовать, не случилось. Для системы учёта это означает расхождение, и закрываем мы это паттерном transactional outbox — подробнее о статусе в roadmap.