関数

関数は call-and-return 型の entry point です。呼び出し元の context を継承し、呼び出し元が cancel されると関数も cancel されます。pool は Lua state を再利用できるため、module global と closure upvalue が 1 つの worker 上で残る場合はありますが、呼び出し間で一貫して共有されるわけではありません。durable state または shared state は関数の外に保存してください。HTTP handler、API endpoint、request lifecycle 内で完了するその他の operation に関数を使います。

関数の呼び出し

funcs.call()で関数を同期的に呼び出します:

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

非ブロッキング実行には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

function invocation と executor option については funcs moduleを参照してください。

コンテキスト伝播

各呼び出しは独自のコンテキストスコープを持つフレームを作成します。子関数は明示的な受け渡しなしに親コンテキストを継承します:

local ctx = require("ctx")

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

呼び出し時にコンテキストを追加:

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

security context も同じように伝播します。呼び出された関数は呼び出し元の actor を参照し、permission を確認できます。access control API については security moduleを参照してください。

レジストリ定義

レジストリレベルでは、関数エントリは次のようになります:

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

関数は HTTP handler、queue consumer、scheduled job など他の runtime component から呼び出すことができ、呼び出し元の security context に基づく permission check の対象になります。

プール

関数は execution を管理する pool 上で実行されます。pool type が scaling 動作を決定します。

Inline は worker pool を使わず、呼び出し元の goroutine で実行されます。embedded context で使います。

Static は固定数の worker を維持します。すべての worker が busy の場合、request は queue に入り、worker concurrency は固定されたままです。

pool:
  type: static
  size: 8
  buffer: 512

Lazy は worker なしで開始し、必要に応じて作成します。idle worker は timeout 後に削除されます。

pool:
  type: lazy
  max_size: 32

Adaptive は測定した throughput と現在の load に基づいて worker 数を調整します。

pool:
  type: adaptive
  max_size: 256
プールタイプを指定しない場合、ランタイムは設定に基づいて選択します。`workers`を設定するとstatic、`max_size`を設定するとlazy、完全な制御には明示的に`type`を設定してください。どちらも設定しない場合、プールは最大16ワーカーのlazyになります。

インターセプター

関数呼び出しはインターセプターチェーンを通過します。インターセプターはビジネスロジックに触れることなく横断的な関心事を処理します。

- 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

組込 interceptor には exponential backoff 付き retry が含まれます。Go で記述された runtime integration は、logging、metrics、tracing、authorization、circuit breaking、request transformation のために追加の interceptor を登録できます。Lua application entry から設定できるのは、runtime に install 済みの interceptor だけです。

チェーンは各呼び出しの前後に実行されます。各インターセプターはリクエストを変更したり、実行をショートサーキットしたり、レスポンスをラップできます。

コントラクト

関数は入出力スキーマをコントラクトとして公開できます。コントラクトはランタイム検証とドキュメント生成を可能にするメソッドシグネチャを定義します。

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"})

contract により、呼び出し元は interface を使いながら implementation を別に選択できます。test、multi-tenant deployment、段階的な migration を支援します。

関数 vs プロセス

関数は呼び出し元の context と lifecycle を継承します。呼び出し元が cancel されると、その function call も cancel されます。HTTP handler や queue consumer 内での execution に適しています。

プロセスはホストコンテキストで独立して実行されます。作成者より長く存続し、メッセージを通じて通信します。バックグラウンド作業にはプロセスを、リクエストスコープの操作には関数を使用してください。