함수
function은 call-and-return entry point입니다. caller context를 inherit하며 caller가 cancel되면 함께 cancel됩니다. pool은 Lua state를 reuse할 수 있으므로 module global과 closure upvalue가 한 worker에서 유지될 수 있지만 call 사이에 일관되게 공유되지는 않습니다. durable 또는 shared state는 function 밖에 저장하십시오. HTTP handler, API endpoint 및 request lifecycle 안에 끝나는 operation에 function을 사용합니다.
함수 호출
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 모듈을 참조하십시오.
컨텍스트 전파
각 호출은 자체 컨텍스트 범위를 가진 프레임을 생성합니다. 자식 함수는 명시적으로 전달하지 않아도 부모 컨텍스트를 상속받습니다:
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도 같은 방식으로 propagate됩니다. called function은 caller actor를 보고 permission을 확인할 수 있습니다. access-control API는 보안 모듈을 참조하십시오.
레지스트리 정의
레지스트리에서 함수 엔트리는 다음과 같이 정의합니다:
- name: get_user
kind: function.lua
source: file://handlers/user.lua
method: get
pool:
type: lazy
max_size: 16
함수는 HTTP 핸들러, 큐 컨슈머, 예약된 작업 등 다양한 런타임 컴포넌트에서 호출할 수 있으며, 호출자의 보안 컨텍스트에 따라 권한이 검사됩니다.
풀
함수는 실행을 관리하는 풀에서 실행됩니다. 풀 타입에 따라 스케일링 방식이 달라집니다.
Inline은 worker pool 없이 caller goroutine에서 실행됩니다. embedded context에 사용됩니다.
Static은 고정된 수의 워커를 유지합니다. 모든 워커가 사용 중이면 요청이 큐에 대기합니다. 리소스 사용량이 예측 가능합니다.
pool:
type: static
size: 8
buffer: 512
Lazy는 빈 상태로 시작하고 필요할 때 워커를 생성합니다. 유휴 워커는 타임아웃 후 제거됩니다. 가변적인 트래픽에 효율적입니다.
pool:
type: lazy
max_size: 32
Adaptive는 처리량에 따라 자동으로 스케일링합니다. 컨트롤러가 성능을 측정하고 현재 부하에 맞게 워커 수를 조정합니다.
pool:
type: adaptive
max_size: 256
인터셉터
함수 호출은 인터셉터 체인을 거칩니다. 인터셉터는 비즈니스 로직을 수정하지 않고 횡단 관심사를 처리합니다.
- 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
built-in interceptor에는 exponential backoff를 사용하는 retry가 포함됩니다. Go로 작성된 runtime integration은 logging, metric, tracing, authorization, circuit breaking, request transformation용 interceptor를 추가로 등록할 수 있습니다. Lua application entry는 runtime에 설치된 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"})
이 추상화를 통해 호출 코드를 변경하지 않고 구현을 교체할 수 있습니다. 테스트, 멀티 테넌트 배포, 점진적 마이그레이션에 유용합니다.
함수 vs 프로세스
함수는 호출자 컨텍스트를 상속받고 호출자 수명에 연결됩니다. 호출자가 취소되면 함수도 취소됩니다. 이를 통해 HTTP 핸들러와 큐 컨슈머에서 직접 실행할 수 있습니다.
프로세스는 호스트 컨텍스트에서 독립적으로 실행됩니다. 생성자보다 오래 지속되며 메시지를 통해 통신합니다. 백그라운드 작업에는 프로세스를, 요청 범위 작업에는 함수를 사용하세요.