장시간 provider prefill과 stream backpressure가 정상 노드를 끊지 않도록 liveness window를 확장하고 Chronos 분리 완료 문서와 잔여 artifact를 정리한다.
124 lines
6.8 KiB
Markdown
124 lines
6.8 KiB
Markdown
---
|
|
spec_doc_type: spec
|
|
spec_id: runtime/edge-node-execution
|
|
status: 구현됨
|
|
source_evidence:
|
|
- type: contract
|
|
path: agent-contract/inner/execution-runtime.md
|
|
notes: Host-neutral provider execution primitives
|
|
- type: contract
|
|
path: agent-contract/inner/edge-node-runtime-wire.md
|
|
notes: Edge-Node registration, execution, tunnel, cancellation, command, and refresh wire
|
|
- type: code
|
|
path: packages/go/execution/types.go
|
|
notes: Provider execution and event types
|
|
- type: code
|
|
path: apps/node/internal/node/runtime_bridge.go
|
|
notes: Protobuf-to-execution translation
|
|
- type: code
|
|
path: apps/edge/internal/transport/server.go
|
|
notes: Edge-side tunnel-tolerant heartbeat and disconnect supervision
|
|
- type: code
|
|
path: apps/node/internal/transport/client.go
|
|
notes: Node-side tunnel-tolerant heartbeat and reconnect transport
|
|
- type: code
|
|
path: apps/edge/internal/service/provider_tunnel.go
|
|
notes: Provider selection, credential binding validation, lease acquisition, and pre-send fencing
|
|
- type: code
|
|
path: apps/node/internal/node/tunnel_handler.go
|
|
notes: Provider tunnel handling and recipient-sealed credential lease consumption
|
|
- type: code
|
|
path: packages/go/credentiallease/envelope.go
|
|
notes: Signed scope validation, recipient sealing, expiry, replay, and exact binding verification
|
|
- type: test
|
|
path: apps/node/internal/node/command_test.go
|
|
notes: Closed provider commands, correlation, and cancellation regressions
|
|
- type: test
|
|
path: apps/edge/internal/transport/heartbeat_test.go
|
|
notes: Edge heartbeat liveness profile regression
|
|
- type: test
|
|
path: apps/node/internal/transport/heartbeat_test.go
|
|
notes: Node heartbeat liveness and idle-connection regressions
|
|
---
|
|
|
|
# Edge-Node Provider Execution
|
|
|
|
## 목적
|
|
|
|
Edge owns provider selection, queue admission, leases, and connection-generation fencing. Node owns local provider adapters and executes normalized runs or provider HTTP tunnels after a ready handshake.
|
|
|
|
The shared `packages/go/execution` package contains provider lifecycle, registry, execution events, failures, cancellation, usage, and optional tunnel/command primitives. It does not manage host programs or durable conversation state.
|
|
|
|
## 기능 목록
|
|
|
|
| 기능 | 설명 |
|
|
|------|------|
|
|
| register/readiness | 등록된 Node의 현재 connection이 readiness를 완료한 뒤에만 dispatch한다. |
|
|
| normalized execution | `adapter + target`으로 provider 실행을 선택하고 ordered `RunEvent` stream을 반환한다. |
|
|
| provider raw tunnel | 선택된 provider의 HTTP/SSE를 `ProviderTunnelRequest`/`ProviderTunnelFrame`으로 relay하며 순서와 단일 terminal outcome을 보장한다. |
|
|
| tunnel-tolerant liveness | Edge와 Node는 30초 heartbeat interval과 45초 response wait를 공통으로 사용해 긴 prompt prefill이나 streaming backpressure 중의 정상 connection을 조기에 끊지 않는다. |
|
|
| reconnect/generation fencing | 현재 connection이 종료되면 해당 generation만 fence하고 Node supervisor가 reconnect한다. Heartbeat wait를 넘긴 경우의 close reason은 `heartbeat_timeout`이다. |
|
|
| cancellation/command | `run_id`로 현재 run만 취소하며 command는 capabilities, transport status, Ollama API tunnel로 제한한다. |
|
|
| managed credential lease | Edge가 principal·route·slot·profile·target·Node·revision·generation을 binding한 sealed lease를 발급하고 Node가 capacity admission 후 provider 실행 직전에만 연다. |
|
|
|
|
## 범위
|
|
|
|
- `session_id`는 event와 command result의 opaque correlation일 뿐이며 같은 값을 재사용해도 모든 run은 독립적이다.
|
|
- provider usage, capacity, queue pressure, lifecycle, reconnect, tool calling은 Edge-Node 실행 경로에서 계속 지원한다.
|
|
- managed mode는 등록과 dispatch 전에 CA로 검증된 Edge/Node workload identity를 요구한다.
|
|
- revoked, disabled, expired, stale, replayed, wrong-recipient, mismatched lease는 provider나 credential fallback 없이 fail closed한다.
|
|
|
|
IOP no longer provides persistent shell sessions, terminal emulation, process resume, local working-directory execution context, arbitrary host commands, or local quota/status probing.
|
|
|
|
## 주요 흐름
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Edge
|
|
participant Node
|
|
participant Provider
|
|
|
|
Node->>Edge: RegisterRequest
|
|
Edge-->>Node: RegisterResponse + config
|
|
Node->>Edge: NodeReadyRequest
|
|
Edge-->>Node: NodeReadyResponse
|
|
Edge->>Node: ProviderTunnelRequest
|
|
Node->>Provider: HTTP/SSE request
|
|
Provider-->>Node: status/header/body stream
|
|
Node-->>Edge: ordered ProviderTunnelFrame stream
|
|
Note over Edge,Node: heartbeat 30s interval / 45s wait
|
|
alt heartbeat wait exceeded
|
|
Edge--xNode: current generation fenced
|
|
Node->>Edge: supervised reconnect
|
|
end
|
|
```
|
|
|
|
## 계약
|
|
|
|
- Edge-Node wire: `agent-contract/inner/edge-node-runtime-wire.md`
|
|
- provider execution primitives: `agent-contract/inner/execution-runtime.md`
|
|
|
|
Heartbeat interval/wait는 protobuf field가 아닌 양쪽 transport 구현의 liveness profile이다. Wire message와 provider response shape은 바뀌지 않는다.
|
|
|
|
## 설정/데이터/이벤트
|
|
|
|
- Edge와 Node의 현재 heartbeat interval은 30초, response wait는 45초다.
|
|
- 이 값은 runtime YAML model config나 `max_tokens`/context 설정이 아니라 transport 구현 상수다.
|
|
- 45초 동안 heartbeat response가 없으면 current connection을 `heartbeat_timeout`으로 닫고 provider resource를 offline 처리한 뒤 reconnect/queue 재평가를 수행한다.
|
|
|
|
## 검증
|
|
|
|
- `go test -count=1 ./packages/go/execution ./apps/node/... ./apps/edge/internal/service`
|
|
- `go test -race -count=1 ./packages/go/execution ./apps/node/internal/node ./apps/edge/internal/service`
|
|
- `go test -count=1 ./apps/node/internal/transport ./apps/edge/internal/transport`
|
|
- `go test -race -count=1 ./apps/node/internal/transport ./apps/edge/internal/transport`
|
|
- 실제 provider tunnel 검증은 5초를 넘는 긴 prefill과 streaming 응답 동안 Node가 connected/healthy를 유지하고, 응답이 정상 terminal을 반환하며, `heartbeat_timeout`이 발생하지 않는지 확인한다.
|
|
|
|
## 한계와 주의사항
|
|
|
|
- 30/45초 liveness profile은 provider 응답 token 상한이나 model context window를 늘리지 않는다. 요청 중단 원인 판정 시 model 설정과 transport disconnect를 별도로 확인한다.
|
|
- 45초를 넘겨 실제 heartbeat response가 없는 connection은 기존과 같이 오프라인 처리하고 reconnect한다.
|
|
|
|
## 변경 기록
|
|
|
|
- 2026-08-02: provider tunnel의 긴 prompt prefill과 streaming backpressure를 정상 traffic으로 허용하도록 Edge/Node heartbeat profile을 30초 interval/45초 wait로 복원한 현재 구현과 회귀 검증을 반영했다 (`apps/edge/internal/transport/server.go`, `apps/node/internal/transport/client.go`).
|