OxL Справочник OxL
РусскийEnglish

10.1 Сервисы

oxl
@v(2) pub(api) service Users {
  @readonly @cache(ttl: USER_CACHE_TTL)
  rpc get(id: UserId) -> User | NotFound

  @idempotent(key: r => r.requestId) @retry(STD_RETRIES)
  rpc create(requestId: RequestId, name: Name, email: Email?) -> User

  @resumable
  rpc watch(id: UserId) -> stream<UserEvent>
}

impl Users {
  dep db: Db
  rpc get(id) { db.find(User, id) ?? fail NotFound{ what: "user" } }
  rpc create(requestId, name, email) { … }
  rpc watch(id) { UserEvents.subscribe(key: id) }
}
  • service объявляет контракт: набор rpc с именованными параметрами и типом результата. Параметры образуют сообщение запроса, результат — сообщение ответа (теги по §9.2).
  • В программе ДОЛЖНА быть ровно одна impl для каждого сервиса, если он не объявлен extern service (клиент к внешнему сервису, §16.3).
  • В impl типы параметров и результата МОГУТ опускаться — берутся из service. Эффекты обработчика не ограничены.
  • Зависимости обработчика объявляются dep имя: Тип (§12.7).
  • Ошибки результата передаются как типизированные детали ошибки gRPC. Код статуса — из @grpc_status(code) на типе ошибки, по умолчанию FAILED_PRECONDITION. NetError ↔ статусы: Timeout — DEADLINE_EXCEEDED, Unavailable — UNAVAILABLE, Cancelled — CANCELLED, AccessDenied — PERMISSION_DENIED/UNAUTHENTICATED, ProtocolError — остальные.

Вызов:

ФормаМаршрутизация
Users.get(id)через кластер (§12.3): локально, если узел обслуживает Users, иначе по сети
Users.at(node).get(id)на конкретный узел кластера
Users.connect(addr, tls: opts)клиент к внешнему адресу; возвращает Client<Users>

Контекст ctx доступен в обработчике и пробрасывается в исходящие вызовы: ctx.caller: Principal, ctx.deadline, ctx.traceId, ctx.meta: Map<str, str>, ctx.node.

duplicate-impl, impl-signature-mismatch, missing-impl, missing-rpc-impl, unknown-rpc

См. также

Исходник: docs/spec/oxl-standard.md