Funktionsaufruf

Die primäre Methode zum Aufrufen anderer Funktionen in Wippy. Führen Sie registrierte Funktionen synchron oder asynchron über Prozesse hinweg aus, mit voller Unterstützung für Kontextpropagierung, Sicherheitsanmeldedaten und Timeouts. Dieses Modul ist zentral für den Aufbau verteilter Anwendungen, bei denen Komponenten kommunizieren müssen.

Laden

local funcs = require("funcs")

call

Ruft eine registrierte Funktion synchron auf. Verwenden Sie dies, wenn Sie ein sofortiges Ergebnis benötigen und darauf warten können.

local result, err = funcs.call("app.api:get_user", user_id)
if err then
    return nil, err
end
print(result.name)
Parameter Typ Beschreibung
target string Funktions-ID im Format "namespace:name"
...args any Argumente, die an die Funktion übergeben werden

Gibt zurück: result, error

Der Target-String folgt dem Muster namespace:name, wobei namespace das Modul und name die spezifische Funktion identifiziert.

async

Startet einen asynchronen Funktionsaufruf und gibt sofort ein Future zurück. Verwenden Sie dies für lang laufende Operationen, bei denen Sie nicht blockieren möchten, oder wenn Sie mehrere Operationen parallel ausführen möchten.

-- Schwere Berechnung starten ohne zu blockieren
local future, err = funcs.async("app.process:analyze_data", large_dataset)
if err then
    return nil, err
end

-- Andere Arbeit erledigen während die Berechnung läuft...

-- Auf Ergebnis warten wenn bereit
local ch = future:response()
local payload, ok = ch:receive()
if ok then
    local result = payload:data()
end
Parameter Typ Beschreibung
target string Funktions-ID im Format "namespace:name"
...args any Argumente, die an die Funktion übergeben werden

Gibt zurück: Future, error

new

Erstellt einen neuen Executor zum Aufbauen von Funktionsaufrufen mit benutzerdefiniertem Kontext. Verwenden Sie dies, wenn Sie Request-Kontext propagieren, Sicherheitsanmeldedaten setzen oder Timeouts konfigurieren müssen.

local exec = funcs.new()

Gibt zurück: Executor, error

Executor

Builder für Funktionsaufrufe mit benutzerdefinierten Kontextoptionen. Methoden geben neue Executor-Instanzen zurück (unveränderliche Verkettung), sodass Sie eine Basiskonfiguration wiederverwenden können.

with_context

Fügt Kontextwerte hinzu, die der aufgerufenen Funktion zur Verfügung stehen. Verwenden Sie dies, um request-spezifische Daten wie Trace-IDs, Benutzersitzungen oder Feature-Flags zu propagieren.

-- Request-Kontext an nachgelagerte Services propagieren
local exec = funcs.new():with_context({
    request_id = ctx.get("request_id"),
    feature_flags = {dark_mode = true}
})

local user, err = exec:call("app.api:get_user", user_id)
Parameter Typ Beschreibung
values table Schlüssel-Wert-Paare zum Hinzufügen zum Kontext

Gibt zurück: Executor, error

with_actor

Setzt den Sicherheits-Actor für Autorisierungsprüfungen in der aufgerufenen Funktion. Verwenden Sie dies beim Aufrufen einer Funktion im Namen eines bestimmten Benutzers.

local security = require("security")
local actor = security.actor()  -- Actor des aktuellen Benutzers holen

-- Admin-Funktion mit Benutzeranmeldedaten aufrufen
local exec = funcs.new():with_actor(actor)
local result, err = exec:call("app.admin:delete_record", record_id)
if err and err:kind() == "PERMISSION_DENIED" then
    return nil, errors.new("PERMISSION_DENIED", "User cannot delete records")
end
Parameter Typ Beschreibung
actor Actor Sicherheits-Actor (vom Security-Modul)

Gibt zurück: Executor, error

with_scope

Setzt den Sicherheits-Scope für aufgerufene Funktionen. Scopes definieren die verfügbaren Berechtigungen für den Aufruf.

local security = require("security")
local scope = security.new_scope()

local exec = funcs.new():with_scope(scope)
Parameter Typ Beschreibung
scope Scope Sicherheits-Scope (vom Security-Modul)

Gibt zurück: Executor, error

with_options

Setzt Aufrufoptionen wie Timeout und Priorität. Verwenden Sie dies für Operationen, die Zeitlimits benötigen.

-- 5 Sekunden Timeout für externen API-Aufruf setzen
local exec = funcs.new():with_options({timeout = 5000})
local result, err = exec:call("app.external:fetch_data", query)
if err then
    -- Timeout oder anderen Fehler behandeln
end
Parameter Typ Beschreibung
options table Implementierungsspezifische Optionen

Gibt zurück: Executor, error

call / async

Executor-Versionen von call und async, die den konfigurierten Kontext verwenden.

-- Wiederverwendbaren Executor mit Kontext aufbauen
local exec = funcs.new()
    :with_context({trace_id = "abc-123"})
    :with_options({timeout = 10000})

-- Mehrere Aufrufe mit gleichem Kontext machen
local users, _ = exec:call("app.api:list_users")
local posts, _ = exec:call("app.api:list_posts")

Future

Wird von async()-Aufrufen zurückgegeben. Repräsentiert eine laufende asynchrone Operation.

response / channel

Gibt den zugrunde liegenden Channel zum Empfangen des Ergebnisses zurück.

local future, _ = funcs.async("app.api:slow_operation", data)
local ch = future:response()  -- oder future:channel()

local result = channel.select {
    ch:case_receive(),
    timeout:case_receive()
}

Gibt zurück: Channel

is_complete

Nicht-blockierende Prüfung, ob das Future abgeschlossen ist.

while not future:is_complete() do
    -- andere Arbeit erledigen
    time.sleep("100ms")
end
local result, err = future:result()

Gibt zurück: boolean

is_canceled

Gibt true zurück, wenn cancel() auf diesem Future aufgerufen wurde.

if future:is_canceled() then
    print("Operation was canceled")
end

Gibt zurück: boolean

result

Gibt das zwischengespeicherte Ergebnis zurück, wenn abgeschlossen, oder nil wenn noch ausstehend.

local value, err = future:result()
if err then
    print("Failed:", err:message())
elseif value then
    print("Got:", value:data())
end

Gibt zurück: Payload|nil, error|nil

error

Gibt den Fehler zurück, wenn das Future fehlgeschlagen ist.

local err, has_error = future:error()
if has_error then
    print("Error kind:", err:kind())
end

Gibt zurück: error|nil, boolean

cancel

Bricht die asynchrone Operation ab.

future:cancel()

Parallele Operationen

Führen Sie mehrere Operationen gleichzeitig aus mit async und channel.select.

-- Mehrere Operationen parallel starten
local f1, _ = funcs.async("app.api:get_user", user_id)
local f2, _ = funcs.async("app.api:get_orders", user_id)
local f3, _ = funcs.async("app.api:get_preferences", user_id)

-- Auf alle warten mit Channels
local user_ch = f1:channel()
local orders_ch = f2:channel()
local prefs_ch = f3:channel()

local results = {}
for i = 1, 3 do
    local r = channel.select {
        user_ch:case_receive(),
        orders_ch:case_receive(),
        prefs_ch:case_receive()
    }
    if r.channel == user_ch then
        results.user = r.value:data()
    elseif r.channel == orders_ch then
        results.orders = r.value:data()
    else
        results.prefs = r.value:data()
    end
end

Berechtigungen

Funktionsoperationen unterliegen der Sicherheitsrichtlinienauswertung.

Aktion Ressource Beschreibung
funcs.call Funktions-ID Eine bestimmte Funktion aufrufen
funcs.context context with_context() verwenden, um benutzerdefinierten Kontext zu setzen
funcs.security security with_actor() oder with_scope() verwenden

Fehler

Bedingung Art Wiederholbar
Target leer errors.INVALID nein
Namespace fehlt errors.INVALID nein
Name fehlt errors.INVALID nein
Berechtigung verweigert errors.PERMISSION_DENIED nein
Abonnement fehlgeschlagen errors.INTERNAL nein
Funktionsfehler variiert variiert

Siehe Fehlerbehandlung für die Arbeit mit Fehlern.