Funktionen

Funktionen sind Entrypoints mit Aufruf und Rückgabe. Eine Funktion erbt den Kontext ihres Aufrufers und wird abgebrochen, wenn der Aufrufer abgebrochen wird. Pools können Lua-Zustände wiederverwenden; Modulglobale und Closure-Upvalues können daher auf einem Worker erhalten bleiben, werden jedoch nicht zuverlässig zwischen Aufrufen geteilt. Speichern Sie dauerhaften oder gemeinsamen Zustand außerhalb der Funktion. Verwenden Sie Funktionen für HTTP-Handler, API-Endpoints und andere Operationen, die innerhalb eines Anfragelebenszyklus abgeschlossen werden.

Funktionen aufrufen

Rufen Sie Funktionen synchron mit funcs.call() auf:

local funcs = require("funcs")
local result, err = funcs.call("app.api:get_user", user_id)
if err then return nil, err end
return result

Für eine nicht blockierende Ausführung verwenden Sie funcs.async():

local future, err = funcs.async("app.process:analyze", data)
if err then
    return nil, err
end

local ch = future:response()
local payload, open = ch:receive()
if not open then
    return nil, "future response channel closed"
end

local result, err = payload:data()
if err then
    return nil, err
end

Aufruf und Executor-Optionen beschreibt das funcs-Modul.

Kontextweitergabe

Jeder Aufruf erzeugt einen Frame mit eigenem Kontext-Scope. Kindfunktionen erben den Elternkontext ohne explizite Übergabe:

local ctx = require("ctx")

local trace_id = ctx.get("trace_id")
local user_id = ctx.get("user_id")

Fügen Sie beim Aufruf Kontext hinzu:

local funcs = require("funcs")

local exec, err = funcs.new():with_context({trace_id = "abc-123"})
if err then return nil, err end

local result, err = exec:call("app.api:process", data)
if err then return nil, err end
return result

Sicherheitskontext wird auf dieselbe Weise weitergegeben. Aufgerufene Funktionen sehen den Akteur des Aufrufers und können Berechtigungen prüfen. Zugriffskontroll-APIs beschreibt das security-Modul.

Registry-Definition

Auf Registry-Ebene sieht ein Funktionseintrag so aus:

- name: get_user
  kind: function.lua
  source: file://handlers/user.lua
  method: get
  pool:
    type: lazy
    max_size: 16

Andere Runtime-Komponenten wie HTTP-Handler, Queue-Consumer und geplante Aufgaben können Funktionen aufrufen. Die Aufrufe unterliegen Berechtigungsprüfungen anhand des Sicherheitskontexts des Aufrufers.

Pools

Funktionen laufen in Pools, die ihre Ausführung verwalten. Der Pooltyp bestimmt das Skalierungsverhalten.

Inline läuft ohne Worker-Pool in der Goroutine des Aufrufers. Dieser Typ wird für eingebettete Kontexte verwendet.

Static hält eine feste Anzahl Worker bereit. Sind alle Worker belegt, werden Anfragen eingereiht; die Worker-Nebenläufigkeit bleibt dadurch fest.

pool:
  type: static
  size: 8
  buffer: 512

Lazy startet ohne Worker und erzeugt sie bei Bedarf. Inaktive Worker werden nach einem Timeout entfernt.

pool:
  type: lazy
  max_size: 32

Adaptive passt die Worker-Anzahl anhand des gemessenen Durchsatzes und der aktuellen Last an.

pool:
  type: adaptive
  max_size: 256
Wenn Sie keinen Pool-Typ angeben, wählt die Laufzeitumgebung einen basierend auf Ihrer Konfiguration. Setzen Sie workers für static, max_size für lazy, oder setzen Sie explizit type für volle Kontrolle. Ist keines von beiden gesetzt, ist der Pool lazy mit maximal 16 Workern.

Interceptors

Funktionsaufrufe durchlaufen eine Interceptor-Kette. Interceptors behandeln querschnittliche Belange getrennt von der Funktionsimplementierung.

- name: my_function
  kind: function.lua
  source: file://handler.lua
  method: main
  meta:
    options:
      retry:
        max_attempts: 3
        initial_delay: 100
        backoff_factor: 2.0

Zu den integrierten Interceptors gehört Retry mit exponentiellem Backoff. In Go geschriebene Runtime-Integrationen können weitere Interceptors für Logging, Metriken, Tracing, Autorisierung, Circuit Breaking oder Anfragetransformation registrieren; Lua-Anwendungseinträge können nur von der Runtime installierte Interceptors konfigurieren.

Die Kette läuft vor und nach jedem Aufruf. Jeder Interceptor kann die Anfrage ändern, die Ausführung kurzschließen oder die Antwort umschließen.

Contracts

Funktionen können ihre Ein- und Ausgabeschemas als Contracts bereitstellen. Contracts definieren Methodensignaturen für Runtime-Validierung und Dokumentationsgenerierung.

local contract = require("contract")
local sender = contract.get("app.email:sender")
local email = sender:open("app.email:sender_impl")
email:send({to = "user@example.com", subject = "Hello"})

Contracts erlauben Aufrufern, eine Schnittstelle zu verwenden und die Implementierung getrennt auszuwählen. Das unterstützt Tests, mandantenfähige Bereitstellungen und schrittweise Migrationen.

Funktionen und Prozesse

Funktionen erben Kontext und Lebenszyklus des Aufrufers. Wird der Aufrufer abgebrochen, werden auch seine Funktionsaufrufe abgebrochen. Das eignet sich für die Ausführung in HTTP-Handlern und Queue-Consumern.

Prozesse laufen unabhängig mit Host-Kontext. Sie überleben ihren Erzeuger und kommunizieren durch Nachrichten. Verwenden Sie Prozesse für Hintergrundarbeit und Funktionen für anfragegebundene Operationen.