Перейти к содержимому

Контракты

Вызов сервисов через типизированные контракты. Обращение к удалённым API, workflow и функциям с валидацией схем и поддержкой асинхронного выполнения.

local contract = require("contract")

Открыть привязку напрямую по ID:

local greeter, err = contract.open("app.services:greeter")
if err then
return nil, err
end
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_idstringID привязки, поддерживает query-параметры
scopetableЗначения контекста (опционально, переопределяют query-параметры)
optionstableОпции вызова (опционально) — например 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")
ПолеТипОписание
namestringИмя метода
descriptionstringОписание метода
input_schemastable[]Схемы входных данных
output_schemastable[]Схемы выходных данных

Получить список привязок, реализующих контракт:

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_attemptsintМаксимум попыток включая первую (1 отключает retry)
retry.initial_delayint/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.getID контрактаget()
contract.openID привязкиopen(), Contract:open()
contract.implementationsID контракта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