Transport-agnostic API

Принцип: код, который вызывает API, ничего не знает о транспорте. WebSocket, HTTP, WebRTC, MessagePort — взаимозаменяемы без правок UI или бизнес-логики.

Проблема mainstream-подхода

  • REST: код вызывает fetch('/api/users/123') → намертво вшит HTTP, путь, метод.
  • GraphQL: вызов через client.query(...) — привязан к транспорту GraphQL.
  • gRPC: protobuf-схема и stub — нельзя просто заменить транспорт.

Поменять REST → WebSocket → пришлось бы переписать всё.

Идея transport-agnostic

const result = await api.module.method(args);

Это вызов:

  • может пойти по WebSocket к серверу;
  • может пойти через MessagePort к Service Worker;
  • может пойти через WebRTC к peer'у;
  • может быть локальной заглушкой в unit-тесте.

UI этого не знает. Transport — деталь конфигурации.

Реализация в Metacom

  1. Introspection — клиент спрашивает у сервера: «какие у тебя интерфейсы и методы?»
  2. Proxy-объект — на основе ответа строится клиентский SDK: api.users.get(123).
  3. Транспортный адаптер — реализует send(packet) / on(packet). Меняется в одной точке.

Стратегия как паттерн

«Эти интерфейсы можно подменять, и таким образом мы можем реализовывать разные стратегии. Стратегии транспортов, стратегии сториджа, стратегии запуска бизнес-логики.»

Это GoF Strategy на уровне сетевой архитектуры.

Изоморфность

Тот же API-объект работает:

  • В браузерной вкладке (WebSocket к серверу).
  • В Service Worker (WebSocket к серверу, прокси к вкладкам через MessagePort).
  • На сервере (локальный вызов в том же процессе).
  • В тесте (mock-транспорт).

Бизнес-логика пишется один раз, исполняется в любой среде.

Чем это лучше REST/GraphQL

REST GraphQL Transport-agnostic (Metacom)
Сигнатура вызова в UI fetch(url) client.query(gql) api.x.y(args)
Замена транспорта переписать всё переписать клиент поменять адаптер
Локальный вызов имитировать сервер имитировать резолверы подменить адаптер
Тестируемость моки HTTP моки клиента прозрачно

Where it leads

Это фундамент для:

  • Local-first архитектуры (хочешь — иди в сервер, хочешь — в локальный CRDT).
  • P2P (WebRTC заменяет WebSocket — UI не заметил).
  • Изоморфизма (тот же код на клиенте и сервере).

🎓 Источники

См. также