Contracts
Contracts
Seção intitulada “Contracts”Invoque serviços através de contracts tipados. Chame APIs remotas, workflows e funções com validação de schema e suporte a execução assíncrona.
Carregamento
Seção intitulada “Carregamento”local contract = require("contract")Abrindo um Binding
Seção intitulada “Abrindo um Binding”Abrir um binding diretamente por ID:
local greeter, err = contract.open("app.services:greeter")if err then return nil, errend
local result, err = greeter:say_hello("Alice")Com contexto de escopo ou parametros de query:
-- Com tabela de escopolocal svc, err = contract.open("app.services:user", { tenant_id = "acme", region = "us-east"})
-- Com parametros de query (auto-convertido: "true"->bool, numeros->int/float)local api, err = contract.open("app.services:api?debug=true&timeout=5000")
-- Com opções de chamada (terceiro argumento)local inst, err = contract.open("app.services:flaky", nil, { retry = { max_attempts = 5, initial_delay = 100 }})| Parâmetro | Tipo | Descrição |
|---|---|---|
binding_id | string | ID do binding, suporta parametros de query |
scope | table | Valores de contexto (opcional, sobrescreve parametros de query) |
options | table | Opções de chamada (opcional) — ex. retry.max_attempts, retry.initial_delay |
Retorna: Instance, error
Obtendo um Contract
Seção intitulada “Obtendo um Contract”Recuperar definição de contract para introspecção:
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")Definição de Method
Seção intitulada “Definição de Method”| Campo | Tipo | Descrição |
|---|---|---|
name | string | Nome do método |
description | string | Descrição do método |
input_schemas | table[] | Definições de schema de entrada |
output_schemas | table[] | Definições de schema de saída |
Encontrando Implementações
Seção intitulada “Encontrando Implementações”Listar todos os bindings que implementam um contract:
local bindings, err = contract.find_implementations("app.services:greeter")
for _, binding_id in ipairs(bindings) do print(binding_id)endOu via objeto contract:
local c, err = contract.get("app.services:greeter")local bindings, err = c:implementations()Verificando Implementação
Seção intitulada “Verificando Implementação”Verificar se instância implementa um contract:
if contract.is(instance, "app.services:greeter") then instance:say_hello("World")endChamando Métodos
Seção intitulada “Chamando Métodos”Chamada síncrona - bloqueia até completar:
local calc, err = contract.open("app.services:calculator")
local sum, err = calc:add(10, 20)local product, err = calc:multiply(5, 6)Chamadas Assíncronas
Seção intitulada “Chamadas Assíncronas”Adicione sufixo _async para execução assíncrona:
local processor, err = contract.open("app.services:processor")
local future, err = processor:process_async(large_dataset)
-- Fazer outro trabalho...
-- Aguardar resultadolocal ch = future:response()local payload, ok = ch:receive()if ok then local result = payload:data()endVeja Futures para métodos de future.
Abrindo via Contract
Seção intitulada “Abrindo via Contract”Abrir binding através de objeto contract:
local c, err = contract.get("app.services:user")
-- Binding padrãolocal instance, err = c:open()
-- Binding especificolocal instance, err = c:open("app.services:user_impl")
-- Com escopolocal instance, err = c:open(nil, {user_id = 123})local instance, err = c:open("app.services:user_impl", {user_id = 123})Adicionando Contexto
Seção intitulada “Adicionando Contexto”Criar wrapper com contexto pre-configurado:
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()Opções de Chamada
Seção intitulada “Opções de Chamada”Configure retry e outro comportamento de chamada via 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()As opções aplicam-se a cada chamada de método na instância retornada. Apenas erros passíveis de retry disparam retries; erros não passíveis de retry aparecem imediatamente. Encadeável com with_context, with_actor, with_scope.
| Opção | Tipo | Descrição |
|---|---|---|
retry.max_attempts | int | Tentativas máximas incluindo a primeira (1 desativa retry) |
retry.initial_delay | int/duration | Atraso antes do primeiro retry (ms ou string de duração) |
Contexto de Segurança
Seção intitulada “Contexto de Segurança”Definir ator e escopo para autorização:
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()Permissões
Seção intitulada “Permissões”| Permissão | Recurso | Funções |
|---|---|---|
contract.get | id do contract | get() |
contract.open | id do binding | open(), Contract:open() |
contract.implementations | id do contract | find_implementations(), Contract:implementations() |
contract.call | nome do método | chamadas de método sync e async |
contract.context | ”context” | Contract:with_context() |
contract.security | ”security” | Contract:with_actor(), Contract:with_scope() |
| Condição | Tipo |
|---|---|
| Formato de ID de binding inválido | errors.INVALID |
| Contract não encontrado | errors.NOT_FOUND |
| Binding não encontrado | errors.NOT_FOUND |
| Método não encontrado | errors.NOT_FOUND |
| Sem binding padrão | errors.NOT_FOUND |
| Permissão negada | errors.PERMISSION_DENIED |
| Chamada falhou | errors.INTERNAL |