awesome-everything EN
↑ Обратно к восхождению

Очереди, потоки, события

UX при eventual consistency: сделай асинхронный бэкенд мгновенным

Суть Практический проект — построй UI над намеренно лагающим асинхронным бэкендом и сделай его отзывчивым: optimistic UI с rollback, честные pending-состояния, идемпотентные retry и читаемый conflict resolution.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 240 min

Читать про consistency-окно — не то же самое, что спроектировать UI, который его переживёт. Построй небольшое приложение над бэкендом, который намеренно возвращает 202 и пишет ~700мс спустя, затем применяй каждый инструмент юнита, пока опыт не станет мгновенным и честным — с доказуемо обработанными failure mode.

Цель

Преврати ментальную модель юнита в рабочий фронтенд: предсказывай-и-сверяй там, где можешь, показывай честное pending-состояние там, где не можешь, ключуй retry и разрешай реальный конфликт читаемо — доказывая каждое поведение воспроизводимым тестом.

Проект
0 из 6
Цель

Построй приложение задач/заметок над намеренно асинхронным бэкендом (POST возвращает 202, consumer применяет запись ~700мс спустя, с инжектируемым уровнем сбоев), чтобы каждое действие пользователя ощущалось отзывчивым и ни один failure mode — ложный успех, бесконечный спиннер, double-submit, тихая перезапись, нарушение read-your-writes — не мог случиться.

Требования
Критерии приёмки
  • Демо (или тест), показывающее, что упавшая optimistic-запись чисто откатывается к состоянию до мутации, без осиротевшего предсказания на экране.
  • Тест, доказывающий, что путь timeout срабатывает, когда consumer не подтверждает — pending-состояние разрешается в affordance 'всё ещё в обработке / повторить', а не крутится вечно.
  • Тест, доказывающий, что два быстрых сабмита с одним idempotency key дают ровно один серверный эффект (одна строка, одно списание), а не два.
  • Демо, показывающее, что read-your-own-writes держится: изменение пользователя остаётся видимым через consistency-окно, и итоговый refresh сверяется с ним, а не стирает его.
  • Короткий разбор, связывающий каждое поведение UI с правилом юнита (predict vs pending, когда держишь предсказание vs сверенное значение, почему конфликт разрешён именно так).
Senior-стретч
  • Замени reconciliation на polling push-каналом (WebSocket/SSE), сигнализирующим, когда consumer закончил, и покажи, как consistency-окно закрывается на событии, а не по таймеру.
  • Добавь реальный CRDT (например, Yjs/Automerge) для коллаборативного текстового поля и покажи, как два клиента сходятся к одному документу без потерянных правок, затем сравни с версией на LWW.
  • Добавь offline-очередь: записи, сделанные офлайн, эхаются локально, ставятся в очередь со своими idempotency key и сбрасываются по порядку при reconnect без дублирования эффектов.
  • Добавь наблюдаемость: покажи живую задержку consistency-окна (accepted → readable) как метрику и построй её p50/p99, чтобы видеть зазор, который прячет твой UX.
Итог

Это цикл, который ты будешь запускать на каждой фиче над асинхронным бэкендом: реши на каждое действие, предсказуем ли результат (optimistic UI с rollback, которого требует контракт) или это дело сервера (честное pending-состояние под защитой timeout), ключуй retry, чтобы двойной клик не списал дважды, эхай записи локально, чтобы read-your-own-writes пережил consistency-окно, и разрешай конфликты читаемо вместо тихой перезаписи. Построив это раз на намеренно лагающем бэкенде, ты доводишь production-версию — где лаг реален и прерывист — до уровня мышечной памяти.

Продолжить восхождение ↑Сквозной pipeline заказов: где живёт каждая гарантия доставки
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.