Contracts
Contracts
Abschnitt betitelt „Contracts“Rufen Sie Services über typisierte Contracts auf. Rufen Sie Remote-APIs, Workflows und Funktionen mit Schema-Validierung und Unterstützung für asynchrone Ausführung auf.
local contract = require("contract")Ein Binding öffnen
Abschnitt betitelt „Ein Binding öffnen“Öffnen Sie ein Binding direkt per ID:
local greeter, err = contract.open("app.services:greeter")if err then return nil, errend
local result, err = greeter:say_hello("Alice")Mit Scope-Kontext oder Query-Parametern:
-- Mit Scope-Tabellelocal svc, err = contract.open("app.services:user", { tenant_id = "acme", region = "us-east"})
-- Mit Query-Parametern (automatisch konvertiert: "true"→bool, Zahlen→int/float)local api, err = contract.open("app.services:api?debug=true&timeout=5000")
-- Mit Aufrufoptionen (drittes Argument)local inst, err = contract.open("app.services:flaky", nil, { retry = { max_attempts = 5, initial_delay = 100 }})| Parameter | Typ | Beschreibung |
|---|---|---|
binding_id | string | Binding-ID, unterstützt Query-Parameter |
scope | table | Kontextwerte (optional, überschreibt Query-Parameter) |
options | table | Aufrufoptionen (optional) — z.B. retry.max_attempts, retry.initial_delay |
Gibt zurück: Instance, error
Einen Contract abrufen
Abschnitt betitelt „Einen Contract abrufen“Rufen Sie die Contract-Definition zur Introspektion ab:
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")Methodendefinition
Abschnitt betitelt „Methodendefinition“| Feld | Typ | Beschreibung |
|---|---|---|
name | string | Methodenname |
description | string | Methodenbeschreibung |
input_schemas | table[] | Eingabe-Schema-Definitionen |
output_schemas | table[] | Ausgabe-Schema-Definitionen |
Implementierungen finden
Abschnitt betitelt „Implementierungen finden“Listen Sie alle Bindings auf, die einen Contract implementieren:
local bindings, err = contract.find_implementations("app.services:greeter")
for _, binding_id in ipairs(bindings) do print(binding_id)endOder über das Contract-Objekt:
local c, err = contract.get("app.services:greeter")local bindings, err = c:implementations()Implementierung prüfen
Abschnitt betitelt „Implementierung prüfen“Prüfen Sie, ob eine Instanz einen Contract implementiert:
if contract.is(instance, "app.services:greeter") then instance:say_hello("World")endMethoden aufrufen
Abschnitt betitelt „Methoden aufrufen“Synchroner Aufruf - blockiert bis zum Abschluss:
local calc, err = contract.open("app.services:calculator")
local sum, err = calc:add(10, 20)local product, err = calc:multiply(5, 6)Asynchrone Aufrufe
Abschnitt betitelt „Asynchrone Aufrufe“Fügen Sie das Suffix _async für asynchrone Ausführung hinzu:
local processor, err = contract.open("app.services:processor")
local future, err = processor:process_async(large_dataset)
-- Andere Arbeit erledigen...
-- Auf Ergebnis wartenlocal ch = future:response()local payload, ok = ch:receive()if ok then local result = payload:data()endSiehe Futures für Future-Methoden.
Via Contract öffnen
Abschnitt betitelt „Via Contract öffnen“Öffnen Sie ein Binding über das Contract-Objekt:
local c, err = contract.get("app.services:user")
-- Standard-Bindinglocal instance, err = c:open()
-- Spezifisches Bindinglocal instance, err = c:open("app.services:user_impl")
-- Mit Scopelocal instance, err = c:open(nil, {user_id = 123})local instance, err = c:open("app.services:user_impl", {user_id = 123})Kontext hinzufügen
Abschnitt betitelt „Kontext hinzufügen“Erstellen Sie einen Wrapper mit vorkonfiguriertem Kontext:
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()Aufrufoptionen
Abschnitt betitelt „Aufrufoptionen“Konfigurieren Sie Retry und anderes Aufrufverhalten ueber 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()Optionen gelten fuer jeden Methodenaufruf der zurueckgegebenen Instanz. Nur retry-faehige Fehler loesen Wiederholungen aus; nicht retry-faehige Fehler erscheinen sofort. Verkettbar mit with_context, with_actor, with_scope.
| Option | Typ | Beschreibung |
|---|---|---|
retry.max_attempts | int | Maximale Versuche inkl. dem ersten (1 deaktiviert Retry) |
retry.initial_delay | int/duration | Verzoegerung vor erstem Retry (ms oder Duration-String) |
Sicherheitskontext
Abschnitt betitelt „Sicherheitskontext“Setzen Sie Actor und Scope für die Autorisierung:
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()Berechtigungen
Abschnitt betitelt „Berechtigungen“| Berechtigung | Ressource | Funktionen |
|---|---|---|
contract.get | Contract-ID | get() |
contract.open | Binding-ID | open(), Contract:open() |
contract.implementations | Contract-ID | find_implementations(), Contract:implementations() |
contract.call | Methodenname | synchrone und asynchrone Methodenaufrufe |
contract.context | ”context” | Contract:with_context() |
contract.security | ”security” | Contract:with_actor(), Contract:with_scope() |
| Bedingung | Art |
|---|---|
| Ungültiges Binding-ID-Format | errors.INVALID |
| Contract nicht gefunden | errors.NOT_FOUND |
| Binding nicht gefunden | errors.NOT_FOUND |
| Methode nicht gefunden | errors.NOT_FOUND |
| Kein Standard-Binding | errors.NOT_FOUND |
| Berechtigung verweigert | errors.PERMISSION_DENIED |
| Aufruf fehlgeschlagen | errors.INTERNAL |