Workflows

Workflows sind dauerhafte, langlebige Vorgänge, die Abstürze und Neustarts überleben. Sie bieten Zuverlässigkeitsgarantien für kritische Geschäftsprozesse wie Zahlungen, Auftragsabwicklung und mehrstufige Genehmigungen.

Warum Workflows?

Funktionen sind flüchtig — wenn der Host abstürzt, geht laufende Arbeit verloren. Workflows speichern ihren Zustand dauerhaft:

Aspekt Funktionen Workflows
Zustand Im Speicher Dauerhaft gespeichert
Absturz Verlorene Arbeit Setzt fort
Dauer Sekunden bis Minuten Stunden bis Monate
Abschluss Best Effort Garantiert

Wie Workflows funktionieren

Workflow-Code sieht aus wie regulärer Lua-Code:

local funcs = require("funcs")
local time = require("time")

local result = funcs.call("app.api:charge_card", payment)
time.sleep("24h")
local status = funcs.call("app.api:check_status", result.id)

if status == "failed" then
    funcs.call("app.api:refund", result.id)
end

Die Workflow-Engine fängt Aufrufe ab und zeichnet Ergebnisse auf. Wenn der Prozess abstürzt, wird die Ausführung aus der Historie wiederholt — gleicher Code, gleiche Ergebnisse.

Wippy behandelt Determinismus automatisch. Operationen wie funcs.call(), time.sleep(), uuid.v4() und time.now() werden abgefangen und ihre Ergebnisse aufgezeichnet. Beim Wiederholen werden aufgezeichnete Werte zurückgegeben, anstatt sie erneut auszuführen.

Workflow-Muster

Saga-Muster

Bei Fehlern kompensieren:

local funcs = require("funcs")

local inventory = funcs.call("app.inventory:reserve", items)
if inventory.error then
    return nil, inventory.error
end

local payment = funcs.call("app.payments:charge", amount)
if payment.error then
    funcs.call("app.inventory:release", inventory.id)
    return nil, payment.error
end

local shipping = funcs.call("app.shipping:create", order)
if shipping.error then
    funcs.call("app.payments:refund", payment.id)
    funcs.call("app.inventory:release", inventory.id)
    return nil, shipping.error
end

return {inventory = inventory, payment = payment, shipping = shipping}

Auf Signale warten

Auf externe Ereignisse warten (Genehmigungsentscheidungen, Webhooks, Benutzeraktionen):

local funcs = require("funcs")

funcs.call("app.approvals:submit", request)

local inbox = process.inbox()
local msg = inbox:receive()  -- blockiert bis Signal ankommt

if msg.approved then
    funcs.call("app.orders:fulfill", request.order_id)
else
    funcs.call("app.notifications:send_rejection", request)
end

Wann was verwenden

Anwendungsfall Wählen
HTTP-Request-Behandlung Funktionen
Datentransformation Funktionen
Hintergrundjobs Prozesse
Benutzersitzungszustand Prozesse
Echtzeit-Messaging Prozesse
Zahlungsverarbeitung Workflows
Auftragsabwicklung Workflows
Mehrtägige Genehmigungen Workflows

Workflows starten

Workflows werden auf dieselbe Weise gestartet wie Prozesse - mit process.spawn() mit einem anderen Host:

-- Workflow auf temporal worker starten
local pid = process.spawn("app.workflows:order_processor", "app:temporal_worker", order_data)

-- Signale an Workflow senden
process.send(pid, "update", {status = "approved"})

Aus Sicht des Aufrufers ist die API identisch. Der Unterschied liegt im Host: Workflows laufen auf einem temporal.worker statt auf einem process.host.

Wenn ein Workflow über process.spawn() Kindprozesse startet, werden diese zu Kind-Workflows beim selben Anbieter, wobei die Beständigkeitsgarantien erhalten bleiben.

Fehler und Supervision

Prozesse können als überwachte Dienste mit process.service laufen:

# Prozessdefinition
- name: session_handler
  kind: process.lua
  source: file://session_handler.lua
  method: main

# Überwachter Dienst, der den Prozess umhüllt
- name: session_manager
  kind: process.service
  process: app:session_handler
  host: app:processes
  lifecycle:
    auto_start: true
    restart:
      max_attempts: 10

Workflows verwenden keine Überwachungsbäume — sie werden automatisch vom Workflow-Anbieter (Temporal) verwaltet. Der Anbieter behandelt Persistenz, Wiederholungen und Wiederherstellung.

Konfiguration

Prozessdefinition (dynamisch gestartet):

- name: order_processor
  kind: workflow.lua
  source: file://order_processor.lua
  method: main
  modules:
    - funcs
    - time

Workflow-Provider:

- name: temporal_worker
  kind: temporal.worker
  client: app:temporal_client
  task_queue: "orders"
  lifecycle:
    auto_start: true

Siehe Temporal für Produktions-Workflow-Infrastruktur.

Siehe auch