프로세스 관리
process 전역은 프로세스 스폰, 메시징, 모니터링, 링크, 명명 및 라이프사이클 제어를 제공합니다.
require() 없이 사용할 수 있으며 modules:에 나열할 필요가 없습니다.
이 페이지는 API 참조입니다. 호출 형식 블록의 id, host, destination, topic, name 같은 플레이스홀더는 애플리케이션 코드가 제공하는 값이며 독립 실행 프로그램이 아닙니다. err 결과와 함께 표시된 호출은 성공 시 문서화된 값을, 실패 시 실패 센티널과 error를 반환합니다. 센티널은 일반적으로 nil이지만 process.set_options는 false를 반환합니다. 애플리케이션 제어 흐름에서 오류를 처리해야 합니다.
프로세스 정보
현재 프레임 ID 또는 프로세스 ID 가져오기:
local frame_id, err = process.id() -- Registry ID of the current function, process, or workflow definition
if err then return nil, err end
local pid, err = process.pid() -- Process ID
if err then return nil, err end
메시지 전송
PID 또는 등록된 이름으로 프로세스에 메시지 전송:
local ok, err = process.send(destination, topic, ...)
| 파라미터 | 타입 | 설명 |
|---|---|---|
destination |
string | PID 또는 등록된 이름 |
topic |
string | 토픽 이름 (@로 시작할 수 없음) |
... |
any | 페이로드 값 |
권한: 대상 PID에 대한 process.send
프로세스 스폰
-- Basic spawn
local pid, err = process.spawn(id, host, ...)
-- With monitoring (receive EXIT events)
local pid, err = process.spawn_monitored(id, host, ...)
-- With linking (receive LINK_DOWN on abnormal exit)
local pid, err = process.spawn_linked(id, host, ...)
-- Both linked and monitored
local pid, err = process.spawn_linked_monitored(id, host, ...)
| 파라미터 | 타입 | 설명 |
|---|---|---|
id |
string | 프로세스 소스 ID (예: "app.workers:handler") |
host |
string | 호스트 ID (예: "app:processes") |
... |
any | 스폰된 프로세스에 전달되는 인수 |
모든 변형에는 프로세스 ID에 대한 process.spawn이 필요합니다. 모니터링 변형에는 process.spawn.monitored, 링크 변형에는 process.spawn.linked도 필요합니다. 런타임 v0.3.32a에서는 모듈 수준 spawn()만 호스트 ID에 대한 process.host를 검사하며, 특수 모듈 수준 변형은 이 호스트 권한 검사를 수행하지 않습니다.
프로세스 제어
-- Forcefully terminate a process
local ok, err = process.terminate(destination)
-- Request graceful cancellation with an optional reason
local ok, err = process.cancel(destination, "shutting down")
| 파라미터 | 타입 | 설명 |
|---|---|---|
destination |
string | PID 또는 등록된 이름 |
reason |
string | 대상에게 전달되는 선택적 이유 |
권한: 대상 PID에 대한 process.terminate, process.cancel
모니터링 및 링킹
기존 프로세스 모니터링 또는 링킹:
-- Monitoring: receive EXIT events when target exits
local ok, err = process.monitor(destination)
local ok, err = process.unmonitor(destination)
-- Linking: bidirectional, receive LINK_DOWN on abnormal exit
local ok, err = process.link(destination)
local ok, err = process.unlink(destination)
권한: 대상 PID에 대한 process.monitor, process.unmonitor, process.link, process.unlink
프로세스 옵션
local options = process.get_options()
local ok, err = process.set_options({trap_links = true})
| 필드 | 타입 | 설명 |
|---|---|---|
trap_links |
boolean | LINK_DOWN 이벤트를 이벤트 채널로 전달할지 여부 |
upgradable |
boolean | 프로세스의 코드가 무효화될 때 OUTDATED 이벤트를 받도록 옵트인 |
인박스 및 이벤트
메시지와 라이프사이클 이벤트를 수신하기 위한 채널 가져오기:
local inbox = process.inbox() -- Message objects from @inbox topic
local events = process.events() -- Lifecycle events from @events topic
이벤트 타입
| 상수 | 설명 |
|---|---|
process.event.CANCEL |
취소 요청됨 |
process.event.EXIT |
모니터링된 프로세스 종료 |
process.event.LINK_DOWN |
링크된 프로세스가 비정상 종료됨 |
process.event.OUTDATED |
프로세스의 코드 또는 임포트된 의존성이 레지스트리에서 변경됨 |
이벤트 필드
| 필드 | 타입 | 설명 |
|---|---|---|
kind |
string | 이벤트 타입 상수 |
from |
string | 소스 PID (OUTDATED에는 없음) |
result |
table | EXIT/LINK_DOWN의 경우: {value, error} 레코드. 프로세스 반환 값은 result.value에, 오류는 result.error에 있습니다 |
reason |
string | CANCEL의 경우: 프로세스가 취소되는 이유 |
sources |
string[] | OUTDATED의 경우: 변경되었거나 전이적으로 영향을 받은 레지스트리 ID |
OUTDATED는 process.set_options({upgradable = true})로 옵트인한 프로세스에만 전달됩니다. 여러 무효화는 sources의 합집합을 포함하는 하나의 대기 이벤트로 결합됩니다. process.upgrade를 호출해 이벤트를 처리하세요.
토픽 구독
커스텀 토픽 구독:
local ch, err = process.listen(topic, options)
if err then return nil, err end
local ok, err = process.unlisten(ch)
if err then return nil, err end
| 파라미터 | 타입 | 설명 |
|---|---|---|
topic |
string | 토픽 이름 (@로 시작할 수 없음) |
options.message |
boolean | true이면 Message 객체 수신; false이면 원시 페이로드 |
메시지 객체
인박스 또는 {message = true}로 수신할 때:
local msg = inbox:receive()
msg:topic() -- string: 토픽 이름
msg:from() -- string: 발신자 PID (알 수 없으면 빈 문자열)
msg:payload() -- Payload: 래퍼 (:data() 호출로 추출); 비어 있으면 nil, 값이 여러 개면 래퍼 테이블
msg:payload():data() -- any: 실제 페이로드 값
동기 호출
프로세스를 스폰하고 결과를 기다렸다가 반환:
local result, err = process.exec(id, host, ...)
권한: 프로세스 id에 대한 process.exec, 호스트 id에 대한 process.host
프로세스 업그레이드
PID를 유지하면서 현재 프로세스를 업그레이드합니다.
아래 두 조각은 순차 작업이 아니라 대안적인 호출 형식입니다.
-- Upgrade to new version, passing state
process.upgrade(id, ...)
-- Keep same definition, re-run with new state
process.upgrade(nil, preserved_state)
process.upgrade는 종료형 제어 이전입니다. 현재 실행을 지우고 같은 PID로 요청된 정의를 시작합니다. 호출 뒤의 코드는 이전 실행에서 수행되지 않습니다.
컨텍스트 스포너
자식 프로세스를 위한 커스텀 컨텍스트가 있는 스포너 생성:
local spawner = process.with_context({request_id = "123"})
권한: "context"에 대한 process.context
옵션이 있는 스포너
process.with_options(options)는 컨텍스트 값 대신 스폰 시 옵션(예: 네트워크 선택자)을 가진 스포너를 생성합니다:
local spawner = process.with_options({network = "app:tor_proxy"})
| 옵션 | 타입 | 설명 |
|---|---|---|
network |
string | 자식의 아웃바운드 연결에 사용할 network.* 엔트리의 레지스트리 ID |
terminal |
string | 자식에 가상 터미널을 붙이는 뷰포트 grant |
권한: "context"에 대한 process.context; 네트워크를 선택하면 해당 네트워크 ID에 대한 network.select가 추가로 필요합니다.
터미널 연결
terminal grant는 viewport:grant()에서 얻으며 자식에게 자체 터미널 포트를 부여하므로, 자식은 터미널 호스트에서와 똑같이 TTY 모듈을 사용할 수 있습니다:
local view = assert(tty.viewport({width = 80, height = 24}))
local child = assert(process.with_options({terminal = assert(view:grant())})
:spawn_monitored("app:child", "app:workers"))
grant는 일회성이며 승인 시점에 소비됩니다: 시작이 거부되면 grant는 해석되지 않은 채 남아 재사용할 수 있고, 포트를 해석한 자식은 이를 영구적으로 소비하며, 터미널 연결을 지원하지 않는 호스트는 옵션을 무시하는 대신 스폰을 거부합니다. 스폰하는 프로세스는 자신이 만든 뷰포트를 통해 자식의 프레임을 계속 읽습니다. Terminal을 참조하세요.
SpawnBuilder 메서드
SpawnBuilder는 불변입니다. 각 구성 메서드는 새 인스턴스를 반환합니다.
spawner:with_context(values) -- 컨텍스트 값 추가
spawner:with_actor(actor) -- 보안 액터 설정
spawner:with_scope(scope) -- 보안 범위 설정
spawner:with_name(name) -- 시작 시 이름 등록; 이미 사용 중이면 spawn이 기존 PID를 반환하고 대기 중인 메시지가 그 PID로 전달됨
spawner:with_message(topic, ...) -- 스폰 후 전송할 메시지 큐에 추가
spawner:with_options(options) -- 스폰 시 옵션 병합 (예: 네트워크)
권한: :with_actor()와 :with_scope()에 대해 "security"에 대한 process.security
스포너 스폰 메서드
spawner:spawn(id, host, ...)
spawner:spawn_monitored(id, host, ...)
spawner:spawn_linked(id, host, ...)
spawner:spawn_linked_monitored(id, host, ...)
모든 SpawnBuilder 스폰 메서드에는 적용 가능한 process.spawn, process.spawn.monitored, process.spawn.linked 권한에 더해 호스트 ID에 대한 process.host가 필요합니다.
스포너 Exec
local result, err = spawner:exec(id, host, ...)
대상 프로세스를 빌더의 컨텍스트, 액터, 스코프 아래에서 동기적으로 실행하고 그 결과 값을 반환합니다 — 모듈 수준 process.exec의 바운드 대응물입니다. 지연된 워커는 with_actor/with_scope로 소유자의 신원을 재구성하여 그를 대신해 실행할 수 있습니다.
권한: 프로세스 id에 대한 process.exec, 호스트 id에 대한 process.host
이름 레지스트리
프로세스를 이름으로 등록하고 PID 대신 해당 이름으로 도달합니다. destination을 받는 모든 함수(send, terminate, cancel, monitor, link, ...)는 PID 대신 등록된 이름을 허용합니다.
local ok, err = process.registry.register(name) -- self, local scope
local pid, err = process.registry.lookup(name)
local ok, err = process.registry.unregister(name)
범위
선택적 scope 인수는 이름의 일관성 보장을 선택하며 기본값은 LOCAL입니다. 전체 모델은 클러스터 가이드를 참조하세요.
| 상수 | 가시성 | 보장 |
|---|---|---|
process.registry.LOCAL |
이 노드만 | 즉각적, 노드-로컬 |
process.registry.EVENTUAL |
클러스터 전체 | 결과적 일관성 (gossip) |
process.registry.CONSISTENT |
클러스터 전체 | 선형화 가능한 싱글톤 (Raft) |
process.registry.STRONG |
클러스터 전체 | Consistent + 모든 살아있는 노드 승인 |
독립 실행형 노드에서는 LOCAL만 사용할 수 있습니다. 클러스터 스코프에는 클러스터링이 필요합니다.
register
local ok, err = process.registry.register(name, pid, scope)
| 파라미터 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
name |
string | 예 | 등록할 이름 | |
pid |
string | 아니오 | 자신 | 등록할 PID; 기본값은 호출 프로세스 |
scope |
number | 아니오 | LOCAL |
위의 범위 상수 중 하나 |
성공 시 true를 반환하고, 실패 시 nil, error를 반환합니다. 충돌(다른 PID로 이미 등록된 이름)은 errors.ALREADY_EXISTS를 반환합니다. 동일한 PID로 같은 이름을 등록하면 멱등합니다. STRONG 등록은 모든 살아있는 노드가 승인하거나 예약 데드라인이 만료될 때까지 차단됩니다; 타임아웃 시 오류를 반환합니다.
다른 PID를 대신하여 등록하면 대상 PID에 대한 process.registry.foreign 권한이 추가로 필요합니다.
lookup
local pid, err = process.registry.lookup(name)
등록된 PID 문자열을 반환하거나, 이름이 등록되지 않은 경우 nil, error를 errors.NOT_FOUND 종류와 함께 반환합니다.
unregister
local ok, err = process.registry.unregister(name, scope)
scope는 기본값이 LOCAL이며 이름이 등록된 범위와 일치해야 합니다. CONSISTENT와 STRONG의 경우, 소유 프로세스만 등록 해제할 수 있습니다; 다른 PID가 소유한 이름을 등록 해제하면 false를 반환합니다. 이름은 소유 프로세스가 종료될 때(그리고 클러스터 범위의 경우 해당 노드가 떠날 때) 자동으로 해제되므로, 명시적인 등록 해제는 조기 해제에 사용됩니다.
권한
권한은 호출 프로세스가 할 수 있는 것을 제어합니다. 모든 검사는 호출자의 보안 컨텍스트(액터)를 대상 리소스에 대해 사용합니다.
정책 평가
정책은 다음을 기반으로 허용/거부할 수 있습니다:
- 액터: 요청을 하는 보안 주체
- 액션: 수행되는 작업 (예:
process.send) - 리소스: 대상 (PID, 프로세스 id, 호스트 id, 또는 이름)
- 속성:
pid(호출자의 프로세스 ID)를 포함한 추가 컨텍스트
권한 레퍼런스
| 권한 | 함수 | 리소스 |
|---|---|---|
process.spawn |
spawn*() |
프로세스 id |
process.spawn.monitored |
spawn_monitored(), spawn_linked_monitored() |
프로세스 id |
process.spawn.linked |
spawn_linked(), spawn_linked_monitored() |
프로세스 id |
process.host |
모듈 수준 spawn(), 모든 SpawnBuilder 스폰 메서드, exec() |
호스트 id |
process.send |
send() |
대상 PID |
process.exec |
exec() |
프로세스 id |
process.terminate |
terminate() |
대상 PID |
process.cancel |
cancel() |
대상 PID |
process.monitor |
monitor() |
대상 PID |
process.unmonitor |
unmonitor() |
대상 PID |
process.link |
link() |
대상 PID |
process.unlink |
unlink() |
대상 PID |
process.context |
with_context(), with_options() |
"context" |
process.security |
:with_actor(), :with_scope() |
"security" |
process.registry.register |
registry.register() |
이름 |
process.registry.unregister |
registry.unregister() |
이름 |
process.registry.foreign |
registry.register() |
대상 PID |
클러스터 이름 범위는 이러한 액션의 범위-접미사 변형(process.registry.register.eventual, .consistent, .strong, 그리고 일치하는 unregister 액션)으로 권한이 부여되므로, 정책이 클러스터 전체 명명과 별도로 로컬 명명을 허용할 수 있습니다.
다중 권한
일부 작업에는 여러 권한이 필요합니다:
| 작업 | 필요한 권한 |
|---|---|
spawn() |
process.spawn + process.host |
모듈 수준 spawn_monitored() |
process.spawn + process.spawn.monitored |
모듈 수준 spawn_linked() |
process.spawn + process.spawn.linked |
모듈 수준 spawn_linked_monitored() |
process.spawn + process.spawn.monitored + process.spawn.linked |
SpawnBuilder:spawn() |
process.spawn + process.host |
SpawnBuilder:spawn_monitored() |
process.spawn + process.spawn.monitored + process.host |
SpawnBuilder:spawn_linked() |
process.spawn + process.spawn.linked + process.host |
SpawnBuilder:spawn_linked_monitored() |
process.spawn + process.spawn.monitored + process.spawn.linked + process.host |
exec() |
process.exec + process.host |
| 커스텀 액터/범위로 스폰 | 스폰 권한 + process.security |
에러
| 조건 | 종류 |
|---|---|
| 컨텍스트 없음 | errors.INTERNAL |
| 프레임 컨텍스트 없음 | errors.INTERNAL |
| 필수 인수 누락 | errors.INVALID |
예약된 토픽 접두사 (@) |
errors.INVALID |
| 대상이 PID도 등록된 이름도 아님 | errors.NOT_FOUND |
| 이름 미등록 | errors.NOT_FOUND |
| 권한 거부됨 | errors.PERMISSION_DENIED |
| 이름 이미 등록됨 | errors.ALREADY_EXISTS |
에러 처리는 에러 처리를 참조하세요.