BACK
Use casesPer-entity grouping — отдельный поток на id
Use cases · 61

Per-entity grouping — отдельный поток на id

Паттерн

WebSocket эмитит события по разным сущностям вперемешку: update id=a, update id=b, update id=a. Каждая сущность должна обновлять СВОЁ состояние независимо. Логически это N потоков, физически — один.

Какую проблему решаем

Один общий reducer с nested maps (state[id].counter += delta) быстро усложняется. Мутации убивают independence сущностей. Тестировать «вот эта последовательность событий приводит к состоянию X для id=a» неудобно.

Операторы и зачем они нужны

  • groupBy(event => event.id) — разбивает один поток на N streams по ключу id.
  • mergeMap(group$ => ...) — подписываемся на каждую группу.
  • scan внутри группы — независимый reducer для конкретной сущности.
  • map — формирует per-entity update.

Подводные камни

  • groupBy при unbounded ids — утечка памяти, группы хранятся вечно. Используйте durationSelector для cleanup.
  • scan с мутацией общего объекта вместо immutable updates — ломает независимость групп.
  • Если важен глобальный порядок изменений между сущностями — mergeMap слишком свободный. Понадобится concatMap или дополнительная синхронизация.

Что в итоге получаем

Каждая сущность получает собственный независимый поток состояния. Логика чистая, тестируемая, без nested mutations.

script.ts // TypeScript
CONSOLE · Console Output
Нажмите на запуск, чтобы увидеть результат...