Ir al contenido

Contratos

Invocar servicios a traves de contratos tipados. Llamar APIs remotas, flujos de trabajo y funciones con validacion de esquema y soporte de ejecución asincrona.

local contract = require("contract")

Abrir un binding directamente por ID:

local greeter, err = contract.open("app.services:greeter")
if err then
return nil, err
end
local result, err = greeter:say_hello("Alice")

Con contexto de alcance o parametros de consulta:

-- Con tabla de alcance
local svc, err = contract.open("app.services:user", {
tenant_id = "acme",
region = "us-east"
})
-- Con parametros de consulta (auto-convertidos: "true"->bool, numeros->int/float)
local api, err = contract.open("app.services:api?debug=true&timeout=5000")
-- Con opciones de llamada (tercer argumento)
local inst, err = contract.open("app.services:flaky", nil, {
retry = { max_attempts = 5, initial_delay = 100 }
})
ParámetroTipoDescripción
binding_idstringID de binding, soporta parametros de consulta
scopetableValores de contexto (opcional, sobrescribe parametros de consulta)
optionstableOpciones de llamada (opcional) — ej. retry.max_attempts, retry.initial_delay

Devuelve: Instance, error

Recuperar definicion de contrato para introspeccion:

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")
CampoTipoDescripción
namestringNombre del método
descriptionstringDescripción del método
input_schemastable[]Definiciones de esquema de entrada
output_schemastable[]Definiciones de esquema de salida

Listar todos los bindings que implementan un contrato:

local bindings, err = contract.find_implementations("app.services:greeter")
for _, binding_id in ipairs(bindings) do
print(binding_id)
end

O via objeto de contrato:

local c, err = contract.get("app.services:greeter")
local bindings, err = c:implementations()

Verificar si una instancia implementa un contrato:

if contract.is(instance, "app.services:greeter") then
instance:say_hello("World")
end

Llamada sincrona - bloquea hasta completar:

local calc, err = contract.open("app.services:calculator")
local sum, err = calc:add(10, 20)
local product, err = calc:multiply(5, 6)

Agregar sufijo _async para ejecución asincrona:

local processor, err = contract.open("app.services:processor")
local future, err = processor:process_async(large_dataset)
-- Hacer otro trabajo...
-- Esperar resultado
local ch = future:response()
local payload, ok = ch:receive()
if ok then
local result = payload:data()
end

Consulte Futures para metodos de future.

Abrir binding a traves de objeto de contrato:

local c, err = contract.get("app.services:user")
-- Binding por defecto
local instance, err = c:open()
-- Binding específico
local instance, err = c:open("app.services:user_impl")
-- Con alcance
local instance, err = c:open(nil, {user_id = 123})
local instance, err = c:open("app.services:user_impl", {user_id = 123})

Crear envoltorio con contexto preconfigurado:

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()

Configura reintentos y otro comportamiento de llamada vía 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()

Las opciones se aplican a cada llamada de método en la instancia devuelta. Solo errores reintentables disparan reintentos; los errores no reintentables aparecen inmediatamente. Encadenable con with_context, with_actor, with_scope.

OpciónTipoDescripción
retry.max_attemptsintIntentos máximos incluyendo el primero (1 desactiva reintentos)
retry.initial_delayint/durationRetardo antes del primer reintento (ms o cadena de duración)

Establecer actor y alcance para autorizacion:

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()
PermisoRecursoFunciones
contract.getid de contratoget()
contract.openid de bindingopen(), Contract:open()
contract.implementationsid de contratofind_implementations(), Contract:implementations()
contract.callnombre de métodollamadas de método sync y async
contract.context”context”Contract:with_context()
contract.security”security”Contract:with_actor(), Contract:with_scope()
CondiciónTipo
Formato de ID de binding invalidoerrors.INVALID
Contrato no encontradoerrors.NOT_FOUND
Binding no encontradoerrors.NOT_FOUND
Método no encontradoerrors.NOT_FOUND
Sin binding por defectoerrors.NOT_FOUND
Permiso denegadoerrors.PERMISSION_DENIED
Llamada fallidaerrors.INTERNAL