Контракты
Контракты
Заголовок раздела «Контракты»Вызов сервисов через типизированные контракты. Обращение к удалённым API, workflow и функциям с валидацией схем и поддержкой асинхронного выполнения.
Загрузка
Заголовок раздела «Загрузка»local contract = require("contract")Открытие привязки
Заголовок раздела «Открытие привязки»Открыть привязку напрямую по ID:
local greeter, err = contract.open("app.services:greeter")if err then return nil, errend
local result, err = greeter:say_hello("Alice")С контекстом области или query-параметрами:
-- С таблицей областиlocal svc, err = contract.open("app.services:user", { tenant_id = "acme", region = "us-east"})
-- С query-параметрами (автоконвертация: "true"→bool, числа→int/float)local api, err = contract.open("app.services:api?debug=true&timeout=5000")
-- С опциями вызова (третий аргумент)local inst, err = contract.open("app.services:flaky", nil, { retry = { max_attempts = 5, initial_delay = 100 }})| Параметр | Тип | Описание |
|---|---|---|
binding_id | string | ID привязки, поддерживает query-параметры |
scope | table | Значения контекста (опционально, переопределяют query-параметры) |
options | table | Опции вызова (опционально) — например retry.max_attempts, retry.initial_delay |
Возвращает: Instance, error
Получение контракта
Заголовок раздела «Получение контракта»Получить определение контракта для интроспекции:
local c, err = contract.get("app.services:greeter")
print(c:id()) -- "app.services:greeter"
local methods = c:methods()for _, m in ipairs(methods) do print(m.name, m.description)end
local method, err = c:method("say_hello")Определение метода
Заголовок раздела «Определение метода»| Поле | Тип | Описание |
|---|---|---|
name | string | Имя метода |
description | string | Описание метода |
input_schemas | table[] | Схемы входных данных |
output_schemas | table[] | Схемы выходных данных |
Поиск реализаций
Заголовок раздела «Поиск реализаций»Получить список привязок, реализующих контракт:
local bindings, err = contract.find_implementations("app.services:greeter")
for _, binding_id in ipairs(bindings) do print(binding_id)endИли через объект контракта:
local c, err = contract.get("app.services:greeter")local bindings, err = c:implementations()Проверка реализации
Заголовок раздела «Проверка реализации»Проверить, реализует ли экземпляр контракт:
if contract.is(instance, "app.services:greeter") then instance:say_hello("World")endВызов методов
Заголовок раздела «Вызов методов»Синхронный вызов — блокируется до завершения:
local calc, err = contract.open("app.services:calculator")
local sum, err = calc:add(10, 20)local product, err = calc:multiply(5, 6)Асинхронные вызовы
Заголовок раздела «Асинхронные вызовы»Добавьте суффикс _async для асинхронного выполнения:
local processor, err = contract.open("app.services:processor")
local future, err = processor:process_async(large_dataset)
-- Делаем другую работу...
-- Ждём результатlocal ch = future:response()local payload, ok = ch:receive()if ok then local result = payload:data()endСм. Futures для методов future.
Открытие через контракт
Заголовок раздела «Открытие через контракт»Открыть привязку через объект контракта:
local c, err = contract.get("app.services:user")
-- Привязка по умолчаниюlocal instance, err = c:open()
-- Конкретная привязкаlocal instance, err = c:open("app.services:user_impl")
-- С областьюlocal instance, err = c:open(nil, {user_id = 123})local instance, err = c:open("app.services:user_impl", {user_id = 123})Добавление контекста
Заголовок раздела «Добавление контекста»Создать обёртку с предварительно настроенным контекстом:
local c, err = contract.get("app.services:user")
local wrapped = c:with_context({ request_id = ctx.get("request_id"), user_id = current_user.id})
local instance, err = wrapped:open()Опции вызова
Заголовок раздела «Опции вызова»Настройте retry и другое поведение вызова через with_options:
local c, err = contract.get("app.services:flaky")
local inst, err = c :with_options({ retry = { max_attempts = 5, initial_delay = 100 } }) :open("app.services:flaky_impl")
local result, err = inst:call()Опции применяются к каждому вызову метода возвращённого экземпляра. Только повторяемые ошибки запускают retry; неповторяемые ошибки возвращаются сразу. Цепочкой с with_context, with_actor, with_scope.
| Опция | Тип | Описание |
|---|---|---|
retry.max_attempts | int | Максимум попыток включая первую (1 отключает retry) |
retry.initial_delay | int/duration | Задержка перед первым retry (ms или строка duration) |
Контекст безопасности
Заголовок раздела «Контекст безопасности»Установить актора и область для авторизации:
local security = require("security")local c, err = contract.get("app.services:admin")
local secured = c:with_actor(security.actor()):with_scope(security.scope())
local admin, err = secured:open()Разрешения
Заголовок раздела «Разрешения»| Разрешение | Ресурс | Функции |
|---|---|---|
contract.get | ID контракта | get() |
contract.open | ID привязки | open(), Contract:open() |
contract.implementations | ID контракта | find_implementations(), Contract:implementations() |
contract.call | имя метода | синхронные и асинхронные вызовы методов |
contract.context | ”context” | Contract:with_context() |
contract.security | ”security” | Contract:with_actor(), Contract:with_scope() |
| Условие | Kind |
|---|---|
| Неверный формат ID привязки | errors.INVALID |
| Контракт не найден | errors.NOT_FOUND |
| Привязка не найдена | errors.NOT_FOUND |
| Метод не найден | errors.NOT_FOUND |
| Нет привязки по умолчанию | errors.NOT_FOUND |
| Доступ запрещён | errors.PERMISSION_DENIED |
| Ошибка вызова | errors.INTERNAL |