API KO - k-p2p-lab/kpl-v3 GitHub Wiki
Wiki home โบ ํ๊ตญ์ด ๋ฌธ์ ยท ์์ด ์๋ฌธ
๋ฌธ์ ์๋ด ยท ์์ค ์ ์ฅ์
Controller์ ๋์๋ณด๋์ ์ด์ API๋ ๋ก๊ทธ์ธ ์ธ์ ์ผ๋ก ๋ณดํธํฉ๋๋ค. ์๋ ์ธ์ฆ์์ ๊ณต๊ฐ ๋ชจ๋ํฐ๋ง ๊ฒฝ๋ก์ ๋ด๋ถ ์๋น์ค ์ธ์ฆ์ ๊ตฌ๋ถํฉ๋๋ค.
Controller๋ ์น ์ ๊ทผ๊ณผ ์ธ์ฆ ์๋๋ฅผ <data-dir>/logs/access.jsonl, auth.jsonl์ ๋ณด์กดํฉ๋๋ค. ๋น๋ฐ๋ฒํธยท์ฟ ํคยท์ธ์ฆ ํค๋ยท์ฟผ๋ฆฌ๋ ๊ธฐ๋กํ์ง ์์ต๋๋ค. ํ๋ยทํ์ ยท์กฐํ ๋ฐฉ๋ฒ์ ์น ์ ๊ทผยท์ธ์ฆ ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค.
| Method | Path | ์ค๋ช |
|---|---|---|
POST |
/api/v1/auth/login |
JSON ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธํ๊ณ ์ธ์ ์ฟ ํค ๋ฐ๊ธ |
GET |
/api/v1/auth/session |
ํ์ฌ ์ฌ์ฉ์ยท์ธ์ ๋ง๋ฃ ์๊ฐ |
POST |
/api/v1/auth/logout |
ํ์ฌ ์ธ์ ๊ณผ SSE ์ฐ๊ฒฐ ์ข ๋ฃ |
GET |
/metrics |
Controller์ ์คํ metric์ Prometheus exposition |
GET |
/api/v1/health |
Controller ์ํ์ Peer ์๊ณ ์ธก์ ์ ์ฐ๋ ํ์ฌ UTC ์๊ฐ |
GET |
/api/v1/ui-config |
๋์๋ณด๋ ๋ฉ๋ด์ ์ฌ์ฉํ๋ PrometheusยทGrafana ๊ฒ์ ํฌํธ |
GET |
/api/v1/prometheus/controller-targets |
Controller ๊ณต๊ฐ metrics ์ฃผ์์ Prometheus HTTP service-discovery group |
GET |
/api/v1/prometheus/agent-targets |
metrics URL์ ์๋ฆฐ online Agent์ Prometheus HTTP service-discovery group |
GET |
/api/v1/snapshot |
๋
ธ๋ peerScores๋ฅผ ํฌํจํ ๋์๋ณด๋ ์ ์ฒด snapshot |
GET |
/api/v1/agents |
Agent ์ํ |
POST |
/api/v1/agents/refresh |
๋ฑ๋ก AgentยทPeer ์ํ ์กฐํ; ?discover=true๋ก ๋๋ฝ๋ Swarm Agent๋ ํ์; ์คํจ ์ ๋ณด ๋ฐํ |
PUT |
/api/v1/agents/{agentID}/capacity |
{capacity: 100}์ผ๋ก Agent๋ณ ์์ธ๊ฐ ์ง์ , {capacity: null}๋ก CLI ๊ธฐ๋ณธ๊ฐ ๋ณต์ |
GET |
/api/v1/nodes |
inspection์ผ๋ก ์์งํ peerScores๋ฅผ ํฌํจํ Peer ์ํ |
GET |
/api/v1/network |
peerScores๊ฐ ํฌํจ๋ Peer, ์ฐ๊ฒฐ edge์ ์ ํ ์งํ |
GET |
/api/v1/bootstrap?runId={runId} |
ํ์ run ID์ ์ํ ์ค๋น ์ํ์ bootstrap peer๋ง ๋ฐํ |
GET |
/api/v1/discovery?runId={runId}&topic={topic}&requesterNodeId={nodeId} |
๋์ผ runยท์ ํํ topic์์ readyยทonline ์ํ์ธ PubSub transport ํ๋ณด |
GET |
/api/v1/events |
์ต๊ทผ trace event |
GET |
/api/v1/stream |
peerScores๋ฅผ ํฌํจํ ์ค์๊ฐ snapshot SSE |
GET |
/api/v1/experiments |
์คํ ์ํ์ activeJobs, completedJobs, failedJobs, canceledJobs counter |
GET / POST
|
/api/v1/scenarios |
์๋๋ฆฌ์ค ์์ฝ ๋ชฉ๋ก ์กฐํ ๋๋ ๊ฒ์ฆํ {name, yaml} ์ ์ฅ |
POST |
/api/v1/scenarios/validate |
์๋ณธ YAML์ ์ ์ฅยท์คํ ์์ด ๊ฒ์ฆ. ๋ก๊ทธ์ธ ํ์ |
GET / PUT / DELETE
|
/api/v1/scenarios/{id} |
์ ์ฅ ์๋๋ฆฌ์ค ํ๋๋ฅผ ๋ถ๋ฌ์ค๊ธฐ, ๊ฐฑ์ ๋๋ ์ญ์ |
GET / POST
|
/api/v1/library-groups |
์๋๋ฆฌ์คยท๊ฒฐ๊ณผ๊ฐ ๊ณต์ ํ๋ ๊ทธ๋ฃน ์กฐํ ๋๋ ๊ทธ๋ฃน ์์ฑ |
PUT |
/api/v1/library-groups/members |
์ ํํ ์๋๋ฆฌ์คยท๊ฒฐ๊ณผ ๋ฌถ์์ ํ ๊ทธ๋ฃน ๋๋ Ungrouped๋ก ์ด๋ |
PATCH / DELETE
|
/api/v1/library-groups/{id} |
์๋๋ฆฌ์คยท๊ฒฐ๊ณผ๋ฅผ ๋ณด์กดํ๋ฉด์ ๊ทธ๋ฃน ์ด๋ฆ ๋ณ๊ฒฝ ๋๋ ๊ทธ๋ฃน ์ญ์ |
GET |
/api/v1/result-storage |
๋ก์ปฌ ์ฌ์ ๊ณต๊ฐยท์์ ๊ธฐ์ค๊ณผ ์บ์๋ NAS ๋ณด๊ด ์ํ. ์์ฒญ ์ค NAS๋ฅผ ์กฐํํ์ง ์์ ์ ์ฅ ์ํ ๋ณ๊ฒฝ ์์๋ง ๋ก์ปฌ ๊ฒฐ๊ณผ ๋ชฉ๋ก์ ๊ฐฑ์ ํ ์ ์๋ resultsRevision ๋ฌธ์์ด์ ํฌํจํฉ๋๋ค. ์ซ์๋ก ๋ณํํ์ง ์๊ณ ํ ํฐ์ผ๋ก ๋น๊ตํ์ญ์์ค. |
GET |
/api/v1/results |
์ด์ Controller ์คํ์์ ์ ์ฅํ ์คํ์ ํฌํจํ๋ ๊ฒฐ๊ณผ ๋ชฉ๋ก |
GET / PUT
|
/api/v1/results/{id}/note |
์คํ๋ณ ๊ณต์ ๋ฉ๋ชจ ์กฐํยท์ ์ฅ. revision์ผ๋ก ๋์ ์์ ์ถฉ๋ ๊ฐ์ง |
GET / PUT
|
/api/v1/result-batches/{batchId}/note |
๊ฐ๋ณ Run ๋ฉ๋ชจ์ ๋ ๋ฆฝ์ ์ธ ๊ทธ๋ฃน ๋ฉ๋ชจ ์กฐํยท์ ์ฅ. revision์ผ๋ก ๋์ ์์ ์ถฉ๋ ๊ฐ์ง |
DELETE |
/api/v1/results/{id} |
๋นํ์ฑ ์ ์ฅ ๊ฒฐ๊ณผ ์ญ์ . ์งํ ์ค ๋ฐฐ์นยท๋ค์ด๋ก๋ ๋ณดํธ |
DELETE |
/api/v1/result-batches/{batchId} |
๊ทธ๋ฃน์ ๋ชจ๋ ์ ์ฅ run๊ณผ ํ๊ท ๋ถ์ ์ญ์ . ์ ์ฒด ๊ตฌ์ฑ์์ ํ์ฑ ์ํยท๋ค์ด๋ก๋๋ฅผ ๋จผ์ ๊ฒ์ฌ |
POST |
/api/v1/result-batches/{batchId}/resume |
์คํจ ๋๋ ์์ ํ interrupted ํ์ฐจ๋ฅผ ์ ์ธํ๊ณ ๋ฏธ์์ ํ์ฐจ๋ง ์ฌ๊ฐ. ๋ฐฐ์นยทํ์ฐจ ID ์ ์ง. ์ฒซ queued run๊ณผ 202, ์งํ ์คยท์ฌ๊ฐ ๋ถ๊ฐ ์ 409, ์๋ ๋ฐฐ์น๋ฉด 404. ๋ก๊ทธ์ธ ์ธ์
๊ณผ X-KPL-Request: dashboard ํ์. |
POST |
/api/v1/result-batches/{batchId}/retry |
์ด์ Peer๋ฅผ ์ ๋ฆฌํ ๋ค ์ ์ฅ๋ ๋ฏธ์๋ฃ ํ์ฐจ๋ฅผ ์ฒซ phase๋ถํฐ ์ฌ์คํ. ์๋ฃ ํ์ฐจยท๋ฐฐ์น IDยทํ์ฐจ ๋ฒํธยทseed ์ ์ง, ์ run ID ์ฌ์ฉ. ์คํจยท์ค๋จยท์ทจ์, ๋จ์ผ ์คํ๊ณผ ๋ง์ง๋ง ํ์ฐจ ์คํจ ํฌํจ. ์ฒซ queued run๊ณผ 202, ์งํ ์คยท์ฌ๊ฐ ๋ถ๊ฐ ์ 409, ์๋ ๋ฐฐ์น๋ฉด 404. ๋ก๊ทธ์ธ ์ธ์
๊ณผ X-KPL-Request: dashboard ํ์. |
POST |
/api/v1/result-batches/{batchId}/append |
์๋ฃ ๊ทธ๋ฃน์ {additionalRuns, expectedRepetitions}๋ก ํ์ฐจ ์ถ๊ฐ. ์ฒซ ์ queued run๊ณผ 202 ๋ฐํ |
GET |
/api/v1/experiments/{id}/analysis |
์ ์ฅ ์ด๋ฒคํธยท๊ด์ธก์น๋ฅผ ๋ถ์ํ ๊ทธ๋ํ ๋ฐ์ดํฐ์ ์ง๊ณ JSON |
GET / POST
|
/api/v1/analysis-jobs/{id} |
๋ฐฑ๊ทธ๋ผ์ด๋ ๋ถ์ ์ํ ์กฐํ / ์ ์. ์ค๋ณต ์์ฒญ ์ฌ์ฌ์ฉ, ?refresh=1๋ก ์ snapshot ๋ถ์ |
GET / HEAD
|
/api/v1/analysis-jobs/{id}/result?jobId={jobId} |
์๋ฒ์ ๋ณด๊ด๋ ์๋ฃ ๋ถ์ JSON ๋ค์ด๋ก๋. ์์
๋ฏธ์๋ฃยท๋ค๋ฅธ attempt๋ 409
|
GET / HEAD
|
/api/v1/analysis-jobs/{id}/summary?jobId={jobId} |
๋น๊ต์ฉ ๊ฒฝ๋ ๋ถ์ JSON. ๋ฉ์์ง๋ณ ๊ฒฝ๋ก์ ์๋ณธ ์๊ณ์ด์ ์ ์ธํ๊ณ ์ง๊ณยท๋ถํฌยท์ ํฉ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ |
GET / POST
|
/api/v1/batch-analysis-jobs/{batchId} |
๋์ผ ๋ฐ๋ณต ์คํ์ ํตํฉ ํ๊ท ์์
์ํ ์กฐํ / ์์. ?refresh=1์ ์ ๋ก๊ทธ ๊ฒฝ๊ณ๋ก ๊ฐฑ์ |
GET / HEAD
|
/api/v1/batch-analysis-jobs/{batchId}/result?jobId={jobId} |
์ ์ฅ๋ ํตํฉ ํ๊ท ๊ณผ ๊ฐ์์ฉ run๋ณ ์ ๋ ฅ ๋ค์ด๋ก๋ |
POST |
/api/v1/downloads |
์ ํํ ์๋๋ฆฌ์คยทRun์ ZIP ๋ค์ด๋ก๋ ์ค๋น |
GET |
/api/v1/downloads/{ticket} |
์ธ์ฆ ํ ๋ง๋ฃ ์๊ฐ์ด ์๋ ์ผํ์ฉ ํฐ์ผ์ ์๋ชจํ๊ณ ZIP ์ ์ก |
GET / HEAD
|
/api/v1/experiments/{id}/download |
์๋๋ฆฌ์คยท๋ฉํ๋ฐ์ดํฐยท์ด๋ฒคํธยท์ ํ์ ๊ด์ธก ํ์ผยทํ์ ์งํ๋ฅผ ZIP์ผ๋ก ๋ค์ด๋ก๋ํ๊ฑฐ๋ ์๋ต ๋ณธ๋ฌธ ์์ด ํฌ๊ธฐ ๊ณ์ฐ |
POST |
/api/v1/experiments |
YAML 1ํ ์คํ ๋๋ JSON {scenario, repetitions}๋ก 1~100ํ ์์ฐจ ์คํ |
POST |
/api/v1/experiments/{id}/stop |
X-KPL-Execution์ผ๋ก ์ง์ ํ ์คํ์ ์ทจ์ํ ๋ค ์ ํ ์๊ฐ ๋ด job ์ข
๋ฃ์ generation-fenced Peer cleanup ์ํ. ๋๋ฝยท๊ณผ๊ฑฐ ์คํ ID๋ 409
|
/api/v1/bootstrap์ runId query parameter๋ ํ์์
๋๋ค. registry๋ ํด๋น run์์ ์ค๋น ์ํ์ด๊ณ ์ ํจํ identity์ address ์ ๋ณด๊ฐ ์๋ boot ๋
ธ๋๋ง ๋ฐํํ๋ฏ๋ก ๋์์ ์คํ๋๋ ์คํ๋ผ๋ฆฌ bootstrap peer๋ฅผ ๋ฐ๊ฒฌํ์ง ์์ต๋๋ค. /api/v1/discovery์๋ ํ์๋ query ์ธ ๊ฐ๊ฐ ๋ชจ๋ ํ์ํ๋ฉฐ ์์ฒญ์ ์์ ์ ์ ์ธํ๊ณ ์ค์ ์ ๋ฌยทmesh ๊ฒฐ๊ณผ๊ฐ ์๋ ์ค์ ์ topic ์ฐธ๊ฐ์๋ฅผ ๋ฐํํฉ๋๋ค. /api/v1/prometheus/agent-targets๋ ๊ธฐ๋ณธ Swarm Prometheus ์ค์ ์ด ์ฌ์ฉํ๋ ์ฝ๊ธฐ ์ ์ฉ ์ด์ endpoint์ด๋ฉฐ offline Agent์ ์ ํจํ metrics URL์ด ์๋ Agent๋ ์ ์ธํฉ๋๋ค.
Bootstrap ์๋ต์ {nodeId, peerId, addresses} ํญ๋ชฉ ๋ฐฐ์ด์ด๋ฉฐ ๋น์ด ์์ผ๋ฉด null์
๋๋ค. Discovery์ ๋ฌ๋ฆฌ bootstrap์ Agent online ์ํ๋ก ํํฐ๋งํ์ง ์์ต๋๋ค. Discovery๋ ํ๋ณด๊ฐ ์์ ๋ ๋น ๋ฐฐ์ด์ ๋ฐํํ๋ฉฐ ๊ฐ ํญ๋ชฉ์๋ subscribed flag๋ ํฌํจํฉ๋๋ค. ์กฐ๊ฑด์ ๋ง๋ ์ ์ฒด ํ๋ณด๋ฅผ ๋ฐํํ๊ณ , ์์ฒญํ๋ Peer๊ฐ ํ ํด๋ก์ง์ ์ค๋ช
ํ rendezvous ์์, connection budget๊ณผ retry๋ฅผ ์ ์ฉํฉ๋๋ค.
/api/v1/prometheus/controller-targets๋ Controller์ --metrics-url (KPL_CONTROLLER_METRICS_URL)์ ๊ด๊ณ ํ๋ฉฐ ๋ฏธ์ค์ ์ []๋ฅผ ๋ฐํํฉ๋๋ค. ์ธ์ฆ ์์ด ์กฐํํ๋ ์ฝ๊ธฐ ์ ์ฉ endpoint์
๋๋ค. URL์ HTTP(S)์ /metrics ๊ฒฝ๋ก์ฌ์ผ ํ๋ฉฐ ์ธ์ฆ์ ๋ณดยทqueryยทfragmentยทloopback/unspecified ์ฃผ์๋ฅผ ํ์ฉํ์ง ์์ต๋๋ค. Swarm helper๊ฐ control ๋
ธ๋ ์ฃผ์์ KPL_HTTP_PORT๋ก ์๋ ์ค์ ํฉ๋๋ค.
POST /api/v1/agents/refresh๋ ๋ก๊ทธ์ธ ์ธ์
๊ณผ X-KPL-Request: dashboard๋ฅผ ์๊ตฌํฉ๋๋ค. Offline์ ํฌํจํ ๋ฑ๋ก Agent์์ ์ต์ AgentยทPeer ์ํ๋ฅผ ์กฐํํฉ๋๋ค. ?discover=true๋ฅผ ๋ถ์ด๋ฉด ์คํ ์ค์ธ Swarm Agent task๋ ํ์ํ์ฌ ๋๋ฝ๋ ๋ฑ๋ก์ ๋ณต๊ตฌํฉ๋๋ค. Controller์ --agent-discovery-dns / KPL_AGENT_DISCOVERY_DNS ์ด๋ฆ์ ์กฐํํ๊ณ ๊ฐ task IP์ 8090 ํฌํธ๋ฅผ ํ์ธํฉ๋๋ค. Swarm stack์ tasks.<stack>_agent๋ฅผ ์๋ ์ง์ ํฉ๋๋ค. Controller์ Docker socket์ ๋ง์ดํธํ๊ฑฐ๋ task๋ฅผ ์ฌ์์ํ๊ฑฐ๋ Peer๋ฅผ ์ ๋ฆฌํ์ง ์์ต๋๋ค.
์ต๋ 4๊ฐ๋ฅผ ๋์์ ํ์ธํ๋ฉฐ ์ ์ฒด ์ ํ ์๊ฐ์ 15์ด์
๋๋ค. DNS ์กฐํ์๋ 3์ด ์ ํ, ํ์์๋ ์ค๋ณต ์ ๊ฑฐํ task ์ฃผ์ 256๊ฐ ์ ํ์ ์ ์ฉํฉ๋๋ค. DNS๊ฐ ์คํจํด๋ ๊ธฐ์กด ๋ฑ๋ก ์ฃผ์๋ ์กฐํํฉ๋๋ค. ๋ฏธ๋ฑ๋กยท๊ต์ฒด๋ Agent์๋ ์ธ์ฆ๋ POST /api/v1/registration/refresh๋ฅผ ์์ฒญํ๋ฉฐ, Agent๊ฐ ์์ ์ Controller URL๊ณผ ์๋น์ค ํค๋ก ์ด Controller์ ๋ค์ ๋ฑ๋กํด์ผ ํฉ๋๋ค. ๋ฏธ๋ฑ๋ก Agent์ ์ํ ์๋ต๋ง์ผ๋ก ๋ฑ๋ก์ ๋ง๋ค์ง ์์ต๋๋ค. ๊ธฐ์กด IDยท์ธ์คํด์ค ์ธ๋ ๊ฒ์ฌ์ ์ ์ฅ๋ ์ฉ๋ยท๋นํ์ฑํ ์ค์ ์ ์ ์งํฉ๋๋ค. ์ด๋ฏธ ๋ฑ๋ก๋ ์ธ์คํด์ค๋ ์ด๋ ฅ ์ฌ์ ์ก์ ๋ค์ ์์ํ์ง ์๊ณ ์ํ๋ง ํ์ธํฉ๋๋ค.
์๋ต์ 200๊ณผ {agents, requested, refreshed, failures}์
๋๋ค. ํ์ ์ discovery: {enabled, addresses, added, error?}๋ ํฌํจํฉ๋๋ค. addresses๋ ์ ํ ์ ์ฉ ์ ์ค๋ณต์ ์ ๊ฑฐํ task ์ฃผ์ ์์ด๋ฉฐ, added๋ ์์ฒญ ์์ ๋น์ ๋ชฉ๋ก์ ์๋ ID ์ค ๊ฐฑ์ ์ ์ฑ๊ณตํ ์์
๋๋ค. ์ฌ๋ฌ ์ฃผ์์์ ๊ฐ์ Agent๋ฅผ ํ์ธํด๋ ์ฑ๊ณต Agent์ ์คํจํ ์๋ ค์ง ID๋ ๊ฐ๊ฐ ํ ๋ฒ๋ง ์ง๊ณํฉ๋๋ค. ์๋ณํ์ง ๋ชปํ task ์ฃผ์๋ ๊ฐ๋ณ ์คํจ๋ก ์ง๊ณํฉ๋๋ค. ๊ฐ ์คํจ์๋ {id, name, error}๊ฐ ์์ผ๋ฉฐ, ๋ฏธ์๋ณ ์ฃผ์๋ ๋น id์ URL์ name์ผ๋ก ์ฌ์ฉํฉ๋๋ค. DNSยท์ค์ ์ค๋ฅ๋ ์ฑ๊ณตํ ๊ฐฑ์ ์ ์ ์งํ ์ฑ discovery.error์ ํ์ํฉ๋๋ค. ์ฐ๊ฒฐ ์คํจ ์ Agent ๊ธฐ๋ก์ ์ญ์ ํ์ง ์์ผ๋ฉฐ Offline ํ์ ์๋ ๊ธฐ์กด heartbeat ๋ง๋ฃ ๊ธฐ์ค์ ์ ์ฉํฉ๋๋ค. ์๋ก๊ณ ์นจยทํ์์ด ์ด๋ฏธ ์งํ ์ค์ด๋ฉด 409, ์๋ชป๋ discover ๊ฐ์ 400์
๋๋ค. task ์์ฒด๊ฐ ์์๋์ง ์๊ฑฐ๋ ์ ์ด API๋ฅผ ์ด์ง ๋ชปํ ๊ฒฝ์ฐ์๋ SwarmยทDocker ์์ ์ค๋ฅ๋ฅผ ํ์ธํด์ผ ํฉ๋๋ค. ๋ฑ๋ก ๋ณต๊ตฌ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด Controller์ Agent ์ด๋ฏธ์ง๋ฅผ ํจ๊ป ๊ฐฑ์ ํ๊ณ stack ์ค์ ์ ์ฌ๋ฐฐํฌํ์ญ์์ค.
PUT /api/v1/agents/{agentID}/capacity๋ ๋ก๊ทธ์ธ ์ธ์
๊ณผ X-KPL-Request: dashboard๋ฅผ ์๊ตฌํฉ๋๋ค. ํ์ capacity ํ๋๋ ์์ ์ ์ ๋๋ ์์ธ๊ฐ์ ์ญ์ ํ๋ null์ ๋ฐ์ต๋๋ค. ์ ์ ์๋ ํ๋ยท์์ยท0 ์ดํ ๊ฐ์ 400์
๋๋ค. ๊ฐฑ์ ํ Agent์ 200์ ๋ฐํํ๋ฉฐ, ์๋ ID๋ 404, ์ด ๊ธฐ๋ฅ ์ง์์ ๋ณด๊ณ ํ์ง ์๋ Agent๋ 409์
๋๋ค. ๋ฑ๋ก๋ ์คํ๋ผ์ธ Agent๋ ์ค์ ํ ์ ์์ต๋๋ค. ์ ์ฅ ์คํจ ์ ์ค๋ฅ๋ฅผ ๋ฐํํ๊ณ ํ์ฌ ์ค์ ์ ๋ณ๊ฒฝํ์ง ์์ต๋๋ค.
Agent ๋ ์ฝ๋์๋ defaultCapacity(์์ CLI ๊ฐ), ์ ํ์ capacityOverride(์ ์ฅ ์์ธ๊ฐ), capacityPending(์ ์ฉ ํ์ธ ๋๊ธฐ)์ ์ ๊ณตํฉ๋๋ค. capacity๋ Controller๊ฐ ํ์ฌ ๋ฐฐ์น์ ์ฌ์ฉํ๋ ํ๋์
๋๋ค. ๋ฑ๋กยทheartbeat ์๋ต์ X-KPL-Agent-Capacity, X-KPL-Agent-Capacity-Revision์ผ๋ก ์ค์ ์ ์ ๋ฌํ๋ฉฐ heartbeat ์๋ต์ ๊ธฐ์กด 204๋ฅผ ์ ์งํฉ๋๋ค. Agent๋ ์์ฑ admission๊ณผ ๊ฐ์ ์ ๊ธ ์๋ ์ค์ ์ ์ ์ฉํ๊ณ ๋ค์ ๋ณด๊ณ ์ ์ค์ capacity์ capacityRevision์ ๋ณด๋
๋๋ค. ํ์ฌ ์ค์ ์ ํ์ธํ ๋ณด๊ณ ๋ง ์ฉ๋ ์ฆ๊ฐ๋ฅผ ํ์ฉํ๋ฏ๋ก ์ง์ฐ๋ ๋ณด๊ณ ๊ฐ ๊ฐ์ ์ค์ ์ ์ทจ์ํ์ง ์์ต๋๋ค. Controller ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ์ agent-capacities.json์ ์์ธ๊ฐ์ ์ ์ฅํ๋ฉฐ ํ์ผ์ด ์์๋๋ฉด ํ๋๋ฅผ ์์ ๋ณต์ํ์ง ์๊ณ Controller ์์์ ์ค๋จํฉ๋๋ค.
Agent์ ๋ก์ปฌ ์ฉ๋ ์ ํ ๋๋ฌธ์ create-node ์์ฒญ์ ๊ฑฐ์ ํ๋ฉด Peer๋ฅผ ๋ง๋ค๊ธฐ ์ ์ 429๋ฅผ ๋ฐํํฉ๋๋ค. Controller๋ ํด๋น ์์ฝ์ ํด์ ํ๊ณ ๊ธฐ์กด ์์
์ปจํ
์คํธ ์์์ ๋ฐฐ์น๋ฅผ ๋๊ธฐยท์ฌ์๋ํฉ๋๋ค. ๋ค๋ฅธ ์์ฑ ์ค๋ฅ ์ฒ๋ฆฌ๋ ์ ์งํฉ๋๋ค.
PUT /api/v1/agents/{agentID}/enabled์ {"enabled": true} ๋๋ {"enabled": false}๋ฅผ ๋ณด๋ด ์ฐธ์ฌ ์ฌ๋ถ๋ฅผ ์ค์ ํ๋ฉฐ ๊ฐฑ์ ํ Agent๋ฅผ 200์ผ๋ก ๋ฐํํฉ๋๋ค. ๋๋ฝยทnullยทboolean ์ด์ธ ๊ฐยท์ ์ ์๋ ํ๋๋ 400, ์กด์ฌํ์ง ์๋ Agent๋ 404์
๋๋ค. ๋ก๊ทธ์ธ๊ณผ X-KPL-Request: dashboard๊ฐ ํ์ํฉ๋๋ค. ์ ์ธ๋ Agent๋ disabled: true๋ก ํ์ํ๋ฉฐ ์๋ต ๋๋ false๋ ํ์ฑ์
๋๋ค. online/offline ์ฐ๊ฒฐ ์ํ ๋ฐ capacity ์์ธ ์ค์ ๊ณผ ๋
๋ฆฝ์ ์
๋๋ค.
๋นํ์ฑ Agent๋ ๋ฑ๋ก๊ณผ ์ฐ๊ฒฐ์ ์ ์งํ๋ฉฐ ๊ธฐ์กด Peer ์์
ยท์ ๋ฆฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. ๋ชจ๋ ์ ๋ฐฐ์น ๋ชจ๋, ํ๋์จ์ด ํฉ๊ณยทgauge, Prometheus Agent target discovery, Dashboard ํ ํด๋ก์ง์์ ์ ์ธํฉ๋๋ค. ์ด๋ฏธ ์ ์กํ ์์ฑ ์์ฒญ๊ณผ ๊ธฐ์กด Peer๋ ๊ณ์ ์คํ๋ ์ ์์ผ๋ฉฐ ๋นํ์ฑํ๊ฐ ์ด๋ฅผ ์ข
๋ฃํ๊ฑฐ๋ ์คํ ์ธก์ ๊ฐ์ ๋ค์ ์ฐ์ง๋ ์์ต๋๋ค. ๋นํ์ฑ Agent๋ฅผ ์ง์ ํ explicit/single-Agent join์ ์ฌํ์ฑํ ๋๋ ๊ธฐ์กด ์ทจ์ยท์ ํ์๊ฐ์ ๊ธฐ๋ค๋ฆฝ๋๋ค. ์ ์ฒด REST ์ธ๋ฒคํ ๋ฆฌ์๋ ์์ Peer๋ฅผ ์ ์งํ๋ฉฐ Dashboard๋ ์ค์ ์ฉ Agent ํ์ ๋จ๊ธฐ๊ณ Peer์ ๊ฐ์ ๋ง ์จ๊น๋๋ค. ID๋ณ ์ค์ ์ Controller ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ์ agent-availability.json์ ์ ์ฅํ๊ณ heartbeat๋ก ๋ฎ์ด์ฐ์ง ์์ต๋๋ค. ์ ์ฅ ์คํจ ์ ์ด์ ์ํ๋ฅผ ์ ์งํฉ๋๋ค. ํ์ผ์ ์ฝ์ ์ ์์ผ๋ฉด ๋ฑ๋ก๋ Agent๋ฅผ ๋นํ์ฑ์ผ๋ก ์ ์งํ๋ฉฐ ํ์ผ ๋ณต๊ตฌ ํ Controller๋ฅผ ์ฌ์์ํด์ผ ํฉ๋๋ค.
๋ธ๋ผ์ฐ์ ๋ GET /api/v1/stream?view=dashboard&topology=0์ผ๋ก ์์ํฉ๋๋ค. Overview๋ฅผ ์ผ๋ฉด topology=1๋ก ์ ์ฐ๊ฒฐ์ ์ด๊ณ , ๋๋ฉด topology=0์ผ๋ก ๋์๊ฐ๋๋ค. ์ฐ๊ฒฐ๋ง๋ค ์ฒซ ๋ฐ์ดํฐ snapshot์ ์ ํํ ๋์๋ณด๋ view์ ์ ์ฒด ๊ธฐ์ค ๋ฐ์ดํฐ๋ฅผ ๋ด์ event: snapshot์ด๋ฉฐ, ์ด๋ฅผ ํ ๋ฒ ๋ณด๋ธ ๋ค, ๋ณ๊ฒฝ์ด ์์ผ๋ฉด ์ต๋ ์ด๋น 1ํ event: snapshot_delta๋ฅผ ๋ณด๋
๋๋ค. ์ฌ์ ์์ ํญ์ ์ ์ฒด ๋ฐ์ดํฐ๋ก ์์ํ๋ฏ๋ก Last-Event-ID ์ฌ์ ์ก์ด ํ์ํ์ง ์์ต๋๋ค. ์ ํด ์ฐ๊ฒฐ๋ ์๊ฐ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๊ฐ์ ๊ฐฑ์ ํ๋ฉฐ, 15์ด ๋์ ๋ณ๊ฒฝ์ด ์์ผ๋ฉด event: heartbeat, data: {}๋ฅผ ๋ณด๋
๋๋ค. SSE ์ฃผ์๊ณผ ๋ฌ๋ฆฌ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ฐ์ ์ ์์ด ์ฐ๊ฒฐ ๋ฌด์๋ต ๊ฐ์ง์ ์ฌ์ฉํฉ๋๋ค.
topology=0์ ์์ธ ๋
ธ๋ projection๊ณผ ๊ฐ์ ๊ณ์ฐ์ ์๋ตํ๋ฉฐ nodes: [], edges: []๋ฅผ ๋ณด๋
๋๋ค. ๋ dashboard ๋ชจ๋๋ ๋ชจ๋ topology: {included, total, ready, starting, other}๋ฅผ ํฌํจํ๊ณ , ํผ์ด ์ ์ ์๋ ํ ํด๋ก์ง ์๋ช
์ํ ๊ท์น์ ๋ฐ๋ฆ
๋๋ค. ๋นํ์ฑ Agent์ stoppingยทstoppedยทfailed Peer๋ ์ ์ธํ๋ฉฐ ๋ ์ด์ดยทtopic ํํฐ๋ ํผ์ด ์๋ฅผ ๋ฐ๊พธ์ง ์์ต๋๋ค. Agent, ์คํ ์งํ ์ ๋ณด, ์งํ์ ์ด๋ฒคํธ ์์ฝ์ ๋ ๋ชจ๋ ๋ชจ๋ ์ ๊ณตํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ๋ Overview๊ฐ Off์ด๊ฑฐ๋ ๋ก๋ฉ ์ค์ผ ๋ Transport links๋ฅผ ๋ฏธ์์ผ๋ก ํ์ํฉ๋๋ค. topology๋ฅผ ์๋ตํ๋ฉด ๊ธฐ์กด dashboard ํด๋ผ์ด์ธํธ๋ฅผ ์ํด ๊ทธ๋ํ๋ฅผ ํฌํจํฉ๋๋ค.
snapshot ๊ณ์ฐ์ raw view, ๊ทธ๋ํ๋ฅผ ํฌํจํ๋ dashboard view, ๊ทธ๋ํ๋ฅผ ์ ์ธํ๋ dashboard view๋ณ๋ก ์ต๋ ํ๋์ฉ ๊ณต์ ํฉ๋๋ค. ๊ทธ๋ํ๋ฅผ ์ ์ธํ๋ view๋ ์งํ ์ค์ธ ๊ทธ๋ํ ๊ณ์ฐ์ ๊ธฐ๋ค๋ฆฌ์ง ์์ต๋๋ค. ์ทจ์๋ ์กฐํ๋ ์ฆ์ ๋๊ธฐ๋ฅผ ๋๋ด๊ณ ์ฌ์ ์์ ํด๋น ๋ชจ๋์ ๊ธฐ์กด ๊ณ์ฐ์ ๊ธฐ๋ค๋ฆฝ๋๋ค. ๊ณ์ฐ ์ค์๋ ์ฒซ snapshot ์ด์ ์๋ 15์ด๋ง๋ค heartbeat๋ฅผ ๋ณด๋ ๋๋ค. ์ด๊ธฐ ๋๊ธฐ ์ค heartbeat๋ 30์ด ์ฐ๊ฒฐ ๊ฐ์ ํ์ด๋จธ๋ฅผ ๋ค์ ์ค์ ํ์ง๋ง Dashboard๋ฅผ Live๋ก ํ์ํ๊ฑฐ๋ ๊ธฐ์กด ํ๋ฉด ๋ฐ์ดํฐ๋ฅผ ๊ต์ฒดํ์ง๋ ์์ต๋๋ค. ์งํ ์ฌ๊ตฌ์ฑ์ Run๋ณ ์ ๊ธ์ ์ฌ์ฉํ๋ฉฐ Agent heartbeatยท๋ฐฐ์น๊ฐ ์ฌ์ฉํ๋ Controller ์ธ๋ฒคํ ๋ฆฌ ์ ๊ธ ๋ฐ์์ ์ํํฉ๋๋ค.
๊ทธ๋ํ๋ฅผ ํฌํจํ๋ view์ node metadata์์๋ ์์ฝ ๊ณํ ์ ์ฒด๊ฐ ๋ฐ๋ณต ์ ์ก๋์ง ์๋๋ก networkRequested์ networkSchedule์ ์ ์ธํ๊ณ , ํ์ฌ networkยท์ ์ฉ ์ํยทrevision์ ์ ์งํฉ๋๋ค. ์ ์ฒด REST snapshot์๋ ๋ ๊ณํ์ ๋ณด์กดํฉ๋๋ค.
๊ทธ๋ํ๋ฅผ ํฌํจํ๋ ๋์๋ณด๋ ๋ฐ์ดํฐ๋ ํ์ฌ Peer(stoppingยทstoppedยทfailed ์ ์ธ), ์ ์ฒด ์คํ ์งํ ์ ๋ณด, ํ ํด๋ก์ง, ์งํ, ์ต๊ทผ ์ด๋ฒคํธ ์์ฝ 40๊ฐ๋ฅผ ํฌํจํฉ๋๋ค. ์ด๋ฒคํธ ์์ฝ์ run/node ID, ์ข
๋ฅ, ์๋ Peer, ์๊ฐ, ์ง์ฐ๊ณผ ํ๋ฉด ํ์์ฉ ๋จ์ผ ๊ฐ latencyAvailable, direction, controlType, controlEntries, messageIdCount, peerExchangeCount๋ง ํฌํจํฉ๋๋ค. ์๋ณธ message-ID/cohort ๋ฐฐ์ด๊ณผ ์ด๋ฒคํธ๋ณ bandwidth ํ๋ณธ์ ๋ณด๋ด์ง ์์ต๋๋ค. ์ ์ฒด trace ๊ธฐ๋ก์ ๊ธฐ์กด snapshot API์ ์ ์ฅ๋ ์คํ ๋ด๋ณด๋ด๊ธฐ์ ๋ณด์กด๋ฉ๋๋ค.
๋ณ๊ฒฝ๋ถ์๋ ๋ฐ๋ ์์ญ๋ง ๋ค์ด๊ฐ๋๋ค. agents, nodes, experiments๋ ์ ํ ํ๋ upsert(์ถ๊ฐยท๋ณ๊ฒฝ๋ ํญ๋ชฉ์ ์ ์ฒด ๋ด์ฉ, id ๊ธฐ์ค), remove(์ญ์ ID), order(์์๊ฐ ๋ฐ๋๋ฉด ์ ์ฒด ID ์์)๋ฅผ ๊ฐ๋ ๊ฐ์ฒด์
๋๋ค. ์ญ์ , upsert, ์์ ์ ์ฉ ์์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค. edges, events, metrics, topology๋ ํ๋๊ฐ ์์ผ๋ฉด ๋น ๋ฐฐ์ดยทnull์ ํฌํจํด ํด๋น ์์ญ ์ ์ฒด๋ฅผ ๊ต์ฒดํ๋ฉฐ, ๊ฐฑ์ ์ generatedAt๋ ๋ฐ๋๋๋ค. ์ฐ๊ฒฐ๋ง๋ค ๋ง์ง๋ง์ผ๋ก ์ ๋ฌํ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ์ค์ผ๋ก ๋น๊ตํ๋ฏ๋ก ์ค๊ฐ ๊ฐฑ์ ์ ๊ฑด๋๋ฐ์ด๋ ๋ณ๊ฒฝ์ด ์ ์ค๋์ง ์์ต๋๋ค.
view ์๋ ๊ธฐ์กด GET /api/v1/stream์ ๋ค๋ฅธ ํด๋ผ์ด์ธํธ์์ ํธํ์ ์ํด ์๋ณธ ์ต๊ทผ ์ด๋ฒคํธ ์์ธ๋ฅผ ํฌํจํ ์ ์ฒด snapshot ํ์์ ์ ์งํฉ๋๋ค. ์ ์ ์๋ view ๋๋ ๋น์ด ์์ง ์์ 0/1 ์ด์ธ์ topology ๊ฐ์ 400์ ๋ฐํํฉ๋๋ค. ๋น์ด ์์ง ์์ topology ์ ํ ๊ฐ์๋ view=dashboard๋ ํ์ํฉ๋๋ค. ๋ชจ๋ ๋ชจ๋์ ๊ฐ์ ์ธ์
์ธ์ฆ์ ์ ์ฉํ๊ณ ๋ก๊ทธ์์ยท์ธ์
๋ง๋ฃยทController ์ข
๋ฃ ์ ์ฐ๊ฒฐ์ ๋ซ์ต๋๋ค. ์๋ต์ ์บ์๋ฅผ ๊ธ์งํ๊ณ reverse proxy์ ๋ฒํผ๋ง ๋นํ์ฑํ๋ฅผ ์์ฒญํฉ๋๋ค(X-Accel-Buffering: no).
๋์๋ณด๋๋ ๋ชจ๋ฐ์ผ ๋ฐฑ๊ทธ๋ผ์ด๋ ํญ ๋ฑ ๋ฌธ์๊ฐ ์จ๊ฒจ์ง๊ฑฐ๋ ํ์ด์ง๋ฅผ ๋ ๋ ๋ SSE๋ฅผ ๋ซ์ต๋๋ค. ๋์์ค๋ฉด ์ฐ๊ฒฐ ํ๋๋ฅผ ๋ค์ ์ด์ด ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ต๋๋ค. ํ๋ฉด์ด ๋ณด์ด๋ ๋์ ์คํธ๋ฆผ์ ๊ณ์ ์ด๋ ค ์์ผ๋ฏ๋ก ๋์ ์์ ๋ฐ์ดํธ๋ ์ ์ ํ์ด์ง ๋ค์ด๋ก๋ ํฌ๊ธฐ์ ๋ค๋ฆ ๋๋ค.
์ต์ด snapshot์ 30์ด, ์ดํ snapshotยท๋ณ๊ฒฝ๋ถยทheartbeat ์ฌ์ด๋ 45์ด๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ์ด๋ฅผ ๋์ผ๋ฉด ๋ฉ์ถ ์ฐ๊ฒฐ์ ๋ซ๊ณ SSE ์ค๋ฅ์ ๊ฐ์ ๋ณต๊ตฌ ๊ฒฝ๋ก๋ฅผ ์คํํฉ๋๋ค. ์ธ์
ํ์ธ์ 8์ด ๋ค ์ทจ์ํ๋ฉฐ, ์คํจยท์๊ฐ ์ด๊ณผ์ฌ๋ ๋ค์ ์ฐ๊ฒฐ์ ์๋ํฉ๋๋ค. 401์ Login required ์๋ด ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค. ๋ฐ๋ณต ์คํจ ์ ์ฌ์๋ ๊ฐ๊ฒฉ์ ๋ฌด์์ ํธ์ฐจ๋ฅผ ํฌํจํด ์ฝ 2์ด์์ ์ต๋ 30์ด๊น์ง ๋์ด๋๊ณ , ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ผ๋ฉด ์ด๊ธฐํํฉ๋๋ค. ๋ธ๋ผ์ฐ์ online ์ด๋ฒคํธ๋ ์ค๋๋ ์ฐ๊ฒฐยท์ธ์ฆ ํ์ธ์ ์ทจ์ํ๊ณ ํ๋ฉด์ด ๋ณด์ด๋ฉด ๋ฐ๋ก ์ฌ์ฐ๊ฒฐํฉ๋๋ค. ํ๋ฉด์ ์จ๊ธฐ๊ฑฐ๋ ๋ ๋๋ฉด SSE์ ์งํ ์ค์ธ ์ธ์
ํ์ธ์ ํจ๊ป ์ทจ์ํฉ๋๋ค. ์๋ฒ์ 10์ด ์ฐ๊ธฐ ์ ํ์๊ฐ์ ๊ฐ ์ ์กยทflush ์ค์๋ง ์ ์ฉํ๊ณ ์งํ ํด์ ํ๋ฏ๋ก HTTP/2 ์ ํด ์ฐ๊ฒฐ์ด ๋ค์ heartbeat ์ ์ ๋๊ธฐ์ง ์์ต๋๋ค.
Agent ๋ฑ๋กยทheartbeatยท์ํยท๋์๋ณด๋ ๊ธฐ๋ก์๋ ์ ํ์ ์ผ๋ก resources๊ฐ ํฌํจ๋ฉ๋๋ค. ํ๋๋ sampledAt, ์์ ์ฌ์ฉ ์ฝ์ด ์ cpuCores, ํธ์คํธ ๋
ผ๋ฆฌ CPU ์ cpuCapacityCores, memoryUsageBytes, memoryWorkingSetBytes, containers, measuredContainers, complete, ์ ํ์ error์
๋๋ค. ๋ฒ์๋ Agent์ ์์ ์คํ ์ค Peer์
๋๋ค. ๋ถ๋ถ ์ธก์ ์ complete: false์ ํจ๊ป ์ธก์ ๋ ์ปจํ
์ด๋ ํฉ๊ณ๋ฅผ ๋ณด์กดํ๋ฉฐ ์ธก์ 0๊ฐ๋ ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ด ์์ต๋๋ค. Controller๋ ํ๋ณธ ๊ฒฝ๊ณผ ์๊ฐ์ ์ ๊ทํํ๊ณ Offline ๋๋ 30์ด๋ณด๋ค ์ค๋๋ ํ๋ณธ์ ํ์ฌ ํฉ๊ณ์์ ์ ์ธํฉ๋๋ค. ํธ์คํธ CPU ๋ฐฑ๋ถ์จ์ cpuCores / cpuCapacityCores ร 100์ด๋ฉฐ CPU ์ ๋ฏธ์์ผ ๋ ๋ฐฑ๋ถ์จ๋ง ์๋ตํ๊ณ ๋ฉ๋ชจ๋ฆฌ๋ ์ ์งํฉ๋๋ค.
์ Agent ํ๋ณธ์ ์ ํ์ resources.agent, resources.peers ๊ฐ์ฒด๋ ์ ๊ณตํฉ๋๋ค. ๊ฐ ๊ฐ์ฒด๋ cpuCores, memoryUsageBytes, memoryWorkingSetBytes, containers, measuredContainers, complete๋ฅผ ๊ฐ์ง๋ฉฐ ์์ ํ๋ณธ ์๊ฐ๊ณผ CPU ์๋ฅผ ๊ณต์ ํฉ๋๋ค. ๊ธฐ์กด ์์ ๊ฐ์ Agent + Peers ํฉ๊ณ๋ก ์ ์งํฉ๋๋ค. ๊ฐ ๋ฒ์์ ์ธก์ ์ ํจ์ฑ์ ๋ณ๋๋ก ํ๋จํ๋ฏ๋ก Agent ์ธก์ ์คํจ๊ฐ ์ธก์ ๋ Peer ๊ฐ์ ๊ฐ๋ฆฌ์ง ์์ต๋๋ค. ์ ์ ์กฐํ ๊ฒฐ๊ณผ ๋น Peer ์ธ๋ฒคํ ๋ฆฌ๋ containers: 0, measuredContainers: 0, complete: true์ ์ฌ์ฉ๋ 0์ ๊ธฐ๋กํ๋ฉฐ ๋๋ฝยท์คํจ ํ๋ณธ์ 0์ผ๋ก ๋ฐ๊พธ์ง ์์ต๋๋ค.
GET /api/v1/agents/resources๋ {generatedAt, agents, totals, totalsByScope, services}๋ฅผ ๋ฐํํฉ๋๋ค. totals๋ ์์ cpuCores์ ๋ฉ๋ชจ๋ฆฌ ํ๋๋ฅผ ์ ์งํ๊ณ cpuPercent, cpuCapacityCores, cpuMeasuredAgents, measuredAgents, totalAgents, partialAgents, containers, measuredContainers๋ฅผ ์ ๊ณตํฉ๋๋ค. cpuPercent๋ ์ต์ ํ๋ณธ์ ํธ์คํธ CPU ์ฉ๋์ผ๋ก ๊ฐ์ค ๊ณ์ฐํ๋ฉฐ CPU ์ ๋ฏธ์ Agent๋ ๋ถ์ยท๋ถ๋ชจ ๋ชจ๋ ์ ์ธํฉ๋๋ค. ์์ ์ฝ์ดยท๋ฉ๋ชจ๋ฆฌ ํฉ๊ณ์ Agent ๋ฒ์๋ ๋ ๋์ ์ ์์ผ๋ฏ๋ก ๊ฐ์๋ฅผ ํจ๊ป ํ์ธํ์ญ์์ค. ?format=csv๋ Agent๋ณ complete/partial/๋ฏธ์ ์ํ, cpu_percent_host, cpu_capacity_cores, ๋ ๋ฉ๋ชจ๋ฆฌ ๊ฐ, ์ปจํ
์ด๋ ๊ฐ์์ TOTAL ํ์ ๋ด๋ณด๋
๋๋ค. ๋๋ฝ๊ฐ์ 0์ด ์๋ ๋น ์
์
๋๋ค. totals๋ ๊ธฐ์กด ํฉ๊ณ์ด๋ฉฐ totalsByScope๋ agent_and_peers, agent, peers ๊ฐ๊ฐ์ ์ธก์ ๋ฒ์์ CPU ์ฉ๋ ๊ฐ์ค ๋ถ๋ชจ๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ์ฌ CSV๋ ๋ถ๋ฆฌ๊ฐ์ ๋ณด๊ณ ํ Agent์ ๋ฒ์๋ณ ํ๊ณผ ์ ํจ ์ธก์ ์ด ์๋ ๋ฒ์๋ณ TOTAL ํ์ ์ถ๊ฐํฉ๋๋ค.
GET /api/v1/agents/resources/history?range=1h๋ Prometheus ์๋ณธ ํ๋ณธ์ {from, to, scope, series}๋ก ์กฐํํฉ๋๋ค. ์์ scope๋ all์ด๋ฉฐ ๊ฐ ์๋ฆฌ์ฆ๋ agentId, scope(agent_and_peers, agent, peers), metric, unit, samples: [{at, value}], mean, min, max๋ฅผ ๊ฐ์ง๋๋ค. format=csv&kind=samples ๋๋ format=csv&kind=summary๋ก ๋ค์ด๋ก๋ํฉ๋๋ค. CPU๋ cpu_percent ์งํยทpercent_host ๋จ์(ํธ์คํธ ์ ์ฒด=100%), ๋ฉ๋ชจ๋ฆฌ๋ bytes, ์๊ฐ์ UTC์
๋๋ค. ์ปจํ
์ด๋ ์ธก์ ๋ฒ์๋ containers_expected, containers_measured ์๋ฆฌ์ฆ์ containers ๋จ์๋ก ํฌํจํฉ๋๋ค. ํฉ๊ณ CPU๋ kpl_agent_cpu_usage_percent, ๋ถ๋ฆฌ CPU๋ kpl_agent_component_cpu_usage_percent gauge๋ฅผ ์กฐํํฉ๋๋ค. ์์ ์ฝ์ด gauge์ ์์ง ์์ผ๋ฉฐ ๊ฐ ์ด๋ ฅ์ ํด๋น gauge๊ฐ ์ฒ์ ์์ง๋ ์์ ๋ถํฐ ์์ฑ๋ฉ๋๋ค. range๋ 1mโ24h์
๋๋ค. ๋ถ๋ถ ์ธก์ ๊ฐ๋ ํต๊ณ์ ํฌํจํ๋ ๋๋ฝ ์ฌ์ฉ๋์ ์ถ์ ํ์ง ์์ต๋๋ค. ๋๋ฝ ๊ตฌ๊ฐ๊ณผ ๋น์ ํ ๊ฐ์ ์ ์ธํ๊ณ ๋์ผ ์ค๋ณต์ ํ ๋ฒ๋ง ๊ณ์ฐํ๋ฉฐ ๊ฐ์ Agentยทscopeยท์งํยท์๊ฐ์ ์ถฉ๋๊ฐ์ ์ค๋ฅ์
๋๋ค. ํ๊ท ์ ์ฌ์ฉ ๊ฐ๋ฅํ scrape ํ๋ณธ ๊ธฐ์ค์
๋๋ค.
GET /api/v1/agents/resources/measurements๋ {generatedAt, maxDurationSeconds, measurements}๋ฅผ ๋ฐํํ๋ฉฐ ์ต์ ๊ตฌ๊ฐ๋ถํฐ {id, startedAt, endedAt?, endReason?} ํ์์ผ๋ก ์ ๊ณตํฉ๋๋ค. ๊ฐ์ ๊ฒฝ๋ก์ POST๋ ๊ณต์ ๊ตฌ๊ฐ์ ์์(201)ํ๊ฑฐ๋ ์ด๋ฏธ ์งํ ์ค์ธ ๊ตฌ๊ฐ์ ๋ฐํ(200)ํ๋ฉฐ ์์ง๊ธฐ๋ฅผ ์ฌ์์ํ์ง ์์ต๋๋ค. POST /api/v1/agents/resources/measurements/{id}/stop์ ์ข
๋ฃ ์๊ฐ์ ํ์ ํฉ๋๋ค(200). ๋ฐ๋ณต ์ข
๋ฃ๋ ๊ธฐ์กด ์ข
๋ฃ ์๊ฐ์ ๋ณด์กดํ๊ณ , ์ด์ ID์ ์ข
๋ฃ ์์ฒญ์ ํ์ฌ ๊ตฌ๊ฐ์ ๋ฉ์ถ์ง ์์ต๋๋ค. ๋ณ๊ฒฝ API๋ ๋ค๋ฅธ Dashboard ์์
๊ณผ ๊ฐ์ ๋ธ๋ผ์ฐ์ ์ธ์
ยทCSRF ๊ฒ์ฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ธ๋ฑ์ค๋ Controller ๋ก์ปฌ ์ ์ฅ์์ ์์์ ์ผ๋ก ๊ต์ฒด ์ ์ฅํ๊ณ ์ฌ์์ ์ ๋ณต์ํฉ๋๋ค. ๋ฉํ๋ฐ์ดํฐ ์ฝ๊ธฐยท์ฐ๊ธฐ ์คํจ๋ ์ํ๋ฅผ ๋ฒ๋ฆฌ์ง ์๊ณ 503์ผ๋ก ์๋ฆฝ๋๋ค.
์ด๋ ฅ๊ณผ ๊ตฌ๊ฐ ๋ด๋ณด๋ด๊ธฐ๋ ๊ธฐ์กด ํฉ๊ณ gauge์ ์ kpl_agent_component_* gauge๋ฅผ ์ ํ๋ ๋จ์ผ ์ฟผ๋ฆฌ๋ก ํจ๊ป ์กฐํํฉ๋๋ค. CSV ์นผ๋ผ์ ์ ์งํ๊ณ ํ๋ง๋ค scope๋ก ๊ตฌ๋ถํ๋ฉฐ ํต๊ณ์ ์ค๋ณต ๊ฒ์ฌ๋ scope๋ณ๋ก ๋
๋ฆฝ์ ์
๋๋ค. ๋ถ๋ฆฌ ์๋ฆฌ์ฆ๋ ์
๊ทธ๋ ์ด๋๋ Agent๊ฐ ๋ณด๊ณ ํ ์์ ๋ถํฐ ์์ฑํ๊ณ ๊ธฐ์กด ํฉ๊ณ ์ ์ฉ ์ด๋ ฅ์ ๋ถ๋ฆฌ๊ฐ์ ์ถ์ ํ์ง ์๊ณ ์ ์งํฉ๋๋ค.
DELETE /api/v1/agents/resources/measurements/{id}๋ ์๋ฃ ๊ตฌ๊ฐ ํ๋๋ฅผ ์ญ์ ํ๊ณ ๊ฐฑ์ ํ ์ธก์ ๋ชฉ๋ก์ 200์ผ๋ก ๋ฐํํฉ๋๋ค. ์งํ ์ค ๊ตฌ๊ฐ์ 409, ์๊ฑฐ๋ ์ด๋ฏธ ์ญ์ ๋ ID๋ 404์
๋๋ค. ์ธ์
ยทCSRF ๋ณดํธ์ ๋ก์ปฌ ์์์ ์ ์ฅ์ ์ฌ์ฉํ๋ฉฐ ์ฐ๊ธฐ ์คํจ ์ ์ค์ ๊ธฐ๋ก์ ์ง์ฐ์ง ์๊ณ 503์ ๋ฐํํฉ๋๋ค. ํด๋น ์ ์ฅ ๊ตฌ๊ฐ์ผ๋ก์ ๋ด๋ณด๋ด๊ธฐ๋ ๋ ์ด์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ฏธ ๊ตฌ๊ฐ์ ํ๋ณดํ ๋ค์ด๋ก๋๋ ์๋ฃํ ์ ์์ต๋๋ค. ๊ณต์ฉ Prometheus ํ๋ณธ๊ณผ ์ด๋ฏธ ๋ด๋ ค๋ฐ์ CSV๋ ์ ์งํฉ๋๋ค.
GET /api/v1/agents/resources/measurements/{id}/export๋ ์ ์ฅ๋ ๊ตฌ๊ฐ์ ๋ํด ์์ ๊ฐ์ ์ด๋ ฅ JSON์ ๋ฐํํฉ๋๋ค. format=csv&kind=samples ๋๋ format=csv&kind=summary๋ก ๋ค์ด๋ก๋ํฉ๋๋ค. scrape ์๊ฐ์ด (startedAt, endedAt]์ธ ํ๋ณธ์ ์ ํํ๋ฉฐ ์์ ์ด ๊ฒฝ๊ณ๋ฅผ ๋ณด์กดํ๊ณ , ์ฌ๋ค์ด๋ก๋ ์์๋ ์์ยท์ข
๋ฃ ์๊ฐ์ ์ ์งํฉ๋๋ค. ์งํ ์ค ๊ตฌ๊ฐ์ ์ข
๋ฃ ์ ๊น์ง 409, ์ ์ ์๋ ID ๋๋ CSV ํ๋ณธ ๋ถ์ฌ๋ 404์
๋๋ค. ์งง์ ๊ตฌ๊ฐ๋ ํ์ฉํ์ง๋ง ํ๋ณธ์ด ์์ ์ ์์ต๋๋ค. ๊ตฌ๊ฐ์ 24์๊ฐ ํ ์๋ ์ข
๋ฃ(endReason: "time_limit", ์๋ ์ข
๋ฃ๋ "stopped")ํ๋ฉฐ ์ต๊ทผ 100๊ฐ ๊ตฌ๊ฐ์ ๋ณด์กดํฉ๋๋ค. ํ๋ณธ ๋ณด์กด ๊ธฐ๊ฐ์ Prometheus ์ค์ ์ ๋ฐ๋ฆ
๋๋ค. ์ต๊ทผ ์ด๋ ฅ ์กฐํ์ ๊ฐ์ ๋ด๋ณด๋ด๊ธฐ ์ ํ์ ์ ์ฉํ๊ณ , ๋ค์ด๋ก๋ ์คํจ ํ์๋ ๊ตฌ๊ฐ์ ์ ์งํด ์ฌ์๋ํ ์ ์์ต๋๋ค.
๋ชจ๋ ๋ฆฌ์์ค endpoint๋ ๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค. ์ด๋ ฅ์ Controller์ ์ค์ ๋ Prometheus ์ฃผ์์ ๊ณ ์ ๋ ๋ฆฌ์์ค selector๋ฅผ ์ฌ์ฉํ๋ฉฐ ์์ฒญ์๊ฐ ์์ backend URL์ด๋ PromQL์ ์ง์ ํ ์ ์์ต๋๋ค. upstream ์กฐํ ๋์ 2๊ฐยท15์ดยท16 MiBยท250,000๊ฐ ํ๋ณธ ์ ํ์ ์ ์ฉํฉ๋๋ค. ์๋ชป๋ parameter๋ 400, CSV ํ๋ณธ ๋ถ์ฌ๋ 404, Prometheus ์๋ต ์คํจยทํฌ๊ธฐ ์ด๊ณผยท๋ถ์์ ์๋ต์ 502, ์กฐํ ์ฌ๋กฏ ๋ถ์กฑ์ 503์
๋๋ค. ํ์ฌ CSV๋ Prometheus ์ฐ๊ฒฐ ์์ด ๋์ํฉ๋๋ค. ๋ฆฌ์์ค ์ด๋ ฅ์ ์คํ ZIP๊ณผ ๋ณ๋์ด๋ฉฐ KPL ๋ฆฌ์์ค ๋ชจ๋ํฐ๋ง์ ์ฐธ๊ณ ํ์ญ์์ค.
GET /api/v1/services/resources๋ Dashboard ๋ก๊ทธ์ธ์ด ํ์ํ๋ฉฐ {generatedAt, controllerUptimeSeconds, services}๋ฅผ ๋ฐํํฉ๋๋ค. ์๋น์ค ํญ๋ชฉ์ service, scope, nodeId, nodeName, reportedAt (Controller ์์ ์๊ฐ), state, ์ ํ์ resources์ error๋ฅผ ํฌํจํฉ๋๋ค. ์ํ๋ running, not_running, unknown, stale, awaiting์ด๋ฉฐ ์ปจํ
์ด๋ ์คํ ์ํ์ ์์ ํ๋ณธ ์ ํจ์ฑ์ ๋ณ๊ฐ์
๋๋ค. ์์ ํ๋๋ ๊ธฐ์กด Agent ํฉ๊ณ์ ๊ฐ์ ์๊ฐยทํธ์คํธ CPU ์ยท๋ฉ๋ชจ๋ฆฌยท์ปค๋ฒ๋ฆฌ์ง ํ์์ด๋ฉฐ Agent/Peer ํ์ ๋ฒ์๋ ์์ต๋๋ค. /api/v1/agents/resources๋ services๋ฅผ ์ถ๊ฐํ๋ฉฐ ๊ธฐ์กด Agent ํฉ๊ณ๋ ๋ฐ๊พธ์ง ์์ต๋๋ค.
POST /api/v1/services/resources/report๋ ๋ด๋ถ Bearer ์ธ์ฆ๋ง ํ์ฉํฉ๋๋ค. ๋ณธ๋ฌธ์ {nodeId, nodeName, reportedAt, services: [{service, state, resources?}], error?}์ด๋ฉฐ ๋ณด๊ณ ์ํ๋ running, not_running, unknown์
๋๋ค. ์์ฒญ 128 KiB, ๋
ธ๋๋น ์ค๋ณต ์๋ ์๋น์ค 64๊ฐ, ์๋น์ค๋น ์ปจํ
์ด๋ 512๊ฐ๋ก ์ ํํฉ๋๋ค. ID๋ ๊ธธ์ด๊ฐ ์ ํ๋ ๋จ์ ์๋ณ์์
๋๋ค. ํ๋ณธ ์๊ฐ์ Controller ์๊ณ๋ก ์ ๊ทํํ๊ณ ์์๊ฐ ๋ค๋ฆ์ ๋ณด๊ณ ๋ ๋ฌด์ํฉ๋๋ค. ์บ์๋ ๋
ธ๋ ์ต๋ 512๊ฐ์ด๋ฉฐ 30์ด ๋ค stale, 10๋ถ ๋์ ๋ฏธ์์ ํ๋ฉด ๋ง๋ฃ๋ฉ๋๋ค. ์ ์ ๋ณด๊ณ ๋ 204, ์๋ชป๋ ๋ณด๊ณ 400, ์ธ์ฆ ์คํจ 401, ์บ์ ํ๋ ์ด๊ณผ 503์
๋๋ค. ๋ธ๋ผ์ฐ์ ์ธ์
์ผ๋ก ํ
๋ ๋ฉํธ๋ฆฌ๋ฅผ ์ ์ถํ ์ ์์ต๋๋ค.
์์ ์ด๋ ฅ๊ณผ ์ ์ฅ ๊ตฌ๊ฐ ๋ด๋ณด๋ด๊ธฐ๋ ๊ฐ์ ์ ํ๋ Prometheus ์์ฒญ์ kpl_service_* ์งํ๋ฅผ ํฌํจํฉ๋๋ค. ๊ฐ series์๋ entityType (agent ๋๋ service)์ด ์ถ๊ฐ๋ฉ๋๋ค. ์๋น์ค series์๋ serviceยทnodeId๊ฐ ์์ผ๋ฉฐ agentId๋ ๋น์ฐ๊ณ scope=controller|third_party|monitor๋ฅผ ์ฌ์ฉํฉ๋๋ค. running๊ณผ resource_report_fresh์ ๋จ์๋ boolean์ด๊ณ CPUยท๋ฉ๋ชจ๋ฆฌยท์ปค๋ฒ๋ฆฌ์ง์ ์ด๋ฆ๊ณผ ๋จ์๋ ๊ธฐ์กด๊ณผ ๊ฐ์ต๋๋ค. ํต๊ณ์ ์ค๋ณต ๊ฒ์ฌ ํค๋ scope๋ฟ ์๋๋ผ ์๋น์ค์ ํธ์คํธ๋ฅผ ๋ชจ๋ ๊ตฌ๋ถํฉ๋๋ค. ํ์ฌ ๊ฐยท์ด๋ ฅยท์์ฝ CSV์ ๊ธฐ์กด ์ด ๋ค์ entity_type,service,node_id,node_name์ ์ถ๊ฐํ๋ฉฐ ์ด๋ ฅ์ node_name์ ๋น์๋๋ค. ๊ธฐ์กด Agent ํฉ๊ณ/ํ์ ๋ฒ์ ์ด๋ ฅ๋ ์ ์ง๋ฉ๋๋ค. Controller ๋ฐ ๊ด๋ฆฌ ์๋น์ค๋ฅผ ์ฐธ๊ณ ํ์ธ์.
POST /api/v1/scenarios/validate๋ ์๋ณธ YAML ๋ณธ๋ฌธ(Content-Type: application/yaml)์ ์ต๋ 1 MiB๊น์ง ๋ฐ์ต๋๋ค. ์ ํจํ๋ฉด 200๊ณผ {valid: true, name, phases}๋ฅผ ๋ฐํํฉ๋๋ค. ๋น ์
๋ ฅ, YAML ๋ฌธ๋ฒ ์ค๋ฅ, ์ ์ ์๋ ํ๋, ์๋ชป๋ ์ค์ , ์ฌ๋ฌ YAML ๋ฌธ์๋ 400๊ณผ {error: "โฆ"}๋ฅผ ๋ฐํํ๋ฉฐ ํ์๊ฐ ์ ๊ณตํ๋ ์ค ๋ฒํธ๋ฅผ ๋ณด์กดํฉ๋๋ค. ๋ณธ๋ฌธ ํ๋ ์ด๊ณผ๋ 413์
๋๋ค. ์ ์ฅยท์คํ๊ณผ ๊ฐ์ ํ์๋ฅผ ์ฌ์ฉํ์ง๋ง ๊ธฐ๋ก์ด๋ job์ ๋ง๋ค์ง ์์ผ๋ฉฐ ๋ก๊ทธ์ธ ์ธ์
์ ์ฌ์ฉํฉ๋๋ค. ์ค์ ๊ฒ์ฆ์ด๋ฉฐ Agent ์ฉ๋์ด๋ ์คํ ์ ์ฐ๊ฒฐ์ฑ์ ๊ฒ์ฌํ์ง๋ ์์ต๋๋ค.
์์ฒญ๊ณผ ์๋ต ๋ณธ๋ฌธ์ ๋ชจ๋ JSON์ ์ฌ์ฉํฉ๋๋ค. ํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฐ๋ณ๊ฒ ์ด ์ ์๋๋ก ๋ชฉ๋ก ์๋ต์๋ YAML์ ๋ฃ์ง ์์ผ๋ฏ๋ก, ํธ์งํ๊ธฐ ์ ์ ๊ฐ๋ณ ํญ๋ชฉ์ ์กฐํํ์ญ์์ค.
| Method | Path | ๋ณธ๋ฌธ | ์ฑ๊ณต ์๋ต |
|---|---|---|---|
GET |
/api/v1/scenarios |
์์ |
id, name, createdAt, updatedAt ์์ฝ ๋ชฉ๋ก |
POST |
/api/v1/scenarios |
{ "name": "โฆ", "yaml": "โฆ" } |
์ ์ฒด ํญ๋ชฉ๊ณผ 201
|
GET |
/api/v1/scenarios/{id} |
์์ |
yaml์ ํฌํจํ ์ ์ฒด ํญ๋ชฉ |
PUT |
/api/v1/scenarios/{id} |
{ "name": "โฆ", "yaml": "โฆ" } |
๊ฐฑ์ ๋ ์ ์ฒด ํญ๋ชฉ๊ณผ 200
|
DELETE |
/api/v1/scenarios/{id} |
์์ | ๋ณธ๋ฌธ ์๋ 204
|
์กฐํยท๊ฒ์ฆยท๋ณ๊ฒฝ ๋ชจ๋ ๋ก๊ทธ์ธ ์ธ์
์ด ํ์ํฉ๋๋ค. ๋ณ๊ฒฝ ์์ฒญ์ X-KPL-Request: dashboard ํค๋๋ UI๊ฐ ์๋์ผ๋ก ์ ๋ฌํฉ๋๋ค. ํด์ํ YAML์ด 1 MiB๋ฅผ ๋๋ ๊ฒฝ์ฐ๋ฅผ ํฌํจํ์ฌ ์ ํจํ์ง ์์ ์
๋ ฅ์ 400์
๋๋ค. JSON ์์ฒญ ๋ณธ๋ฌธ์ escape๋ ๋ฌธ์๋ฅผ ๊ณ ๋ คํด 6 * 1 MiB + 64 KiB๊น์ง ํ์ฉํ๋ฉฐ ์ด ํ๋๋ฅผ ๋์ผ๋ฉด 413์
๋๋ค. ์ ์ ์๋ JSON ํ๋์ ํํ JSON ๊ฐ์ ๊ฑฐ๋ถํฉ๋๋ค. ์๊ฑฐ๋ ์ ํจํ์ง ์์ ID๋ 404, ์ ์ฅ์ ์ค๋ฅ๋ 500์
๋๋ค. ID๋ ์๋ฌธ์ 16์ง์ 32์๋ก ๊ตฌ์ฑ๋ฉ๋๋ค.
control-node:8080์ access๊ฐ ํ์ํ Controller ์ฃผ์๋ก ๋ฐ๊พธ๊ณ , ๋จผ์ API ์ธ์ฆ์ผ๋ก KPL_COOKIE_JAR๋ฅผ ์์ฑํ์ญ์์ค.
curl --fail -b "${KPL_COOKIE_JAR:?Log in first}" http://control-node:8080/api/v1/scenarios
curl --fail -X POST http://control-node:8080/api/v1/scenarios \
-H 'Content-Type: application/json' \
-b "${KPL_COOKIE_JAR:?Log in first}" -H 'X-KPL-Request: dashboard' \
--data-binary @- <<'JSON'
{"name":"Smoke baseline","yaml":"version: 2\nname: smoke-baseline\nphases:\n - action: stop-all\n"}
JSON์๋๋ฆฌ์ค์ ์ ์ฅ ๊ฒฐ๊ณผ๋ ์ ๋ฆฌ์ฉ ๊ทธ๋ฃน ๋ชฉ๋ก์ ๊ณต์ ํฉ๋๋ค. ํญ๋ชฉ์ ์ต๋ ํ ๊ทธ๋ฃน์ ์ํ๋ฉฐ, ์์ ๊ธฐ๋ก์ด ์์ผ๋ฉด Ungrouped์ ๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๋ฆฌ์ฉ ๊ทธ๋ฃน์ ๋ฐ๋ณต ์คํ ๋ฐฐ์น, ๋ฐฐ์น ๋ฉ๋ชจ, ์๋๋ฆฌ์ค์ Peer ๊ทธ๋ฃน ๋ฐ ๋ถ์ ๋ฒ์์ ๋ ๋ฆฝ์ ์ ๋๋ค.
๋ชจ๋ endpoint๋ ์ฑ๊ณต ์ ์ ์ฒด snapshot {revision, groups, memberships}๋ฅผ ๋ฐํํฉ๋๋ค. groups๋ {id, name} ๋ฐฐ์ด์ด๋ฉฐ, memberships๋ ํญ๋ชฉ ํค๋ฅผ ๊ทธ๋ฃน ID์ ์ฐ๊ฒฐํฉ๋๋ค. ๊ทธ๋ฃน ID๋ ์๋ฌธ์ 16์ง์ 32์์
๋๋ค. ์ต์ด ๋น snapshot์ {"revision":"0","groups":[],"memberships":{}}์
๋๋ค. ์ดํ revision์ ํด์ํ์ง ์๋ ๋ฌธ์์ด ํ ํฐ์ผ๋ก ์ทจ๊ธํ๊ณ ๋ชจ๋ ๋ณ๊ฒฝ ์์ฒญ์ ์ต์ ๊ฐ์ ์ ๋ฌํ์ญ์์ค.
| Method | Path | JSON ๋ณธ๋ฌธ | ์ฑ๊ณต ์๋ต |
|---|---|---|---|
GET |
/api/v1/library-groups |
์์ | ํ์ฌ snapshot๊ณผ 200
|
POST |
/api/v1/library-groups |
{name, revision} |
์ ๊ทธ๋ฃน์ด ํฌํจ๋ snapshot๊ณผ 201
|
PUT |
/api/v1/library-groups/members |
{groupId, keys, revision} |
์ ํ ํญ๋ชฉ ์ ์ฒด ์ด๋ ํ 200
|
PATCH |
/api/v1/library-groups/{id} |
{name, revision} |
๊ทธ๋ฃน ์ด๋ฆ ๋ณ๊ฒฝ ํ 200
|
DELETE |
/api/v1/library-groups/{id} |
{revision} |
๊ทธ๋ฃน๊ณผ ํด๋น ์์ ๊ธฐ๋ก ์ ๊ฑฐ ํ 200
|
ํญ๋ชฉ ํค๋ ์ ์ฅ ์๋๋ฆฌ์ค์ scenario:<id>, ๋ฐ๋ณต ์คํ ๋ฐฐ์น ์ ์ฒด์ batch:<batchId>, ๋ฐฐ์น ์๋ ๊ฒฐ๊ณผ์ run:<id>์
๋๋ค. ๋ฐฐ์น๋ ์ดํ ์ถ๊ฐยท์ฌ์๋ํ Run์ ํฌํจํ์ฌ ์์ ๊ธฐ๋ก ํ๋๋ฅผ ๊ณต์ ํฉ๋๋ค. ์์์ ํด์ ํ๋ ค๋ฉด groupId: ""๋ก ์ด๋ํ์ญ์์ค. ํญ๋ชฉ ์ด๋๊ณผ ๊ทธ๋ฃน ์ญ์ ๋ ํ๋์ ๋ฉํ๋ฐ์ดํฐ ๊ฐฑ์ ์ผ๋ก ์ ์ฉํฉ๋๋ค. ๊ทธ๋ฃน์ ์ญ์ ํด๋ ์๋๋ฆฌ์ค YAML, Run, ๋ฐฐ์น ์๋ณ์, ๋ฉ๋ชจ, ์์นด์ด๋ธ์ ๋ถ์์ ๋ณด์กด๋๋ฉฐ ํด๋น ํญ๋ชฉ์ Ungrouped๊ฐ ๋ฉ๋๋ค.
๋ชจ๋ endpoint์ ๋ก๊ทธ์ธ ์ธ์
์ด ํ์ํ๋ฉฐ ๋ณ๊ฒฝ ์์ฒญ์๋ X-KPL-Request: dashboard๋ ํ์ํฉ๋๋ค. ์๋ต์ Cache-Control: no-store๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ค๋๋ revision ๋๋ ์ค๋ณต ์ด๋ฆ์ 409๋ฅผ ๋ฐํํ๋ฏ๋ก snapshot์ ๋ค์ ์กฐํํ๊ณ ๋ณ๊ฒฝ ๋ด์ฉ์ ํ์ธํ ๋ค ๋ช
์์ ์ผ๋ก ์ฌ์๋ํ์ญ์์ค. ์๋ ๊ทธ๋ฃน ๋๋ ๊ทธ๋ฃน์ ๋ฃ์ผ๋ ค๋ ํญ๋ชฉ์ ์ฐพ์ ์ ์์ผ๋ฉด 404์
๋๋ค. ์๋ชป๋ ํ๋ยทํคยท์ด๋ฆ๊ณผ ๊ทธ๋ฃนยท์์ ๊ฐ์ ํ๋ ์ด๊ณผ๋ 400์ด๋ฉฐ, ์ ์ ์๋ JSON ํ๋์ ํํ ๊ฐ์ ๊ฑฐ๋ถํฉ๋๋ค. ์์ฒญ ๋ณธ๋ฌธ 2 MiB ์ด๊ณผ๋ 413, ์ ์ฅ์ ์ค๋ฅ๋ 500์
๋๋ค. ๊ฒ์ฆ ์คํจ ์ ์ผ๋ถ ํญ๋ชฉ๋ง ์ด๋ํ์ง ์์ผ๋ฉฐ, ๋คํธ์ํฌ ์๋ต์ด ๋ถํ์คํ๋ฉด ์ฌ์๋ ์ ์ ๋ค์ ์กฐํํ์ญ์์ค.
์ด๋ฆ์ ์๋ค ๊ณต๋ฐฑ์ ์ ๊ฑฐํ ์ ํจ UTF-8 ๋ฌธ์ 1โ128์๋ก, ์ ์ด ๋ฌธ์๋ฅผ ํ์ฉํ์ง ์์ผ๋ฉฐ Unicode ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ์ง ์๋ ๋น๊ต์์ ๊ณ ์ ํด์ผ ํฉ๋๋ค. ์ต๋ ๊ทธ๋ฃน 1,000๊ฐ, ์์ ๊ธฐ๋ก 20,000๊ฐ๋ฅผ ์ง์ํ๊ณ ํ ๋ฒ์ ์ด๋ ์์ฒญ์ ํค 1โ2,000๊ฐ๋ฅผ ๋ฐ์ต๋๋ค. ๋ฉํ๋ฐ์ดํฐ๋ ์ต๋ 4 MiB์ธ ๋ก์ปฌ <data-dir>/library-groups.json์ ์ ์ฅ๋์ด Controller ์ฌ์์ ํ์๋ ์ ์ง๋ฉ๋๋ค. ๊ทธ๋ฃน ๋ณ๊ฒฝ์ ์คํ ์
๋ ฅ์ด๋ ๋ถ์ ํด์๋ฅผ ๋ฐ๊พธ์ง ์์ต๋๋ค. ์ฝ์ ์ ์๊ฑฐ๋ ์ ํจํ์ง ์์ ๋ฉํ๋ฐ์ดํฐ ํ์ผ์ ๋น ๊ฐ์ผ๋ก ๋์ฒดํ์ง ์๊ณ ์ค๋ฅ๋ฅผ ๋ฐํํฉ๋๋ค. UI ์ฌ์ฉ ์์๋ ์๋๋ฆฌ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค.
์ ๊ท ์ ์ถยท์ฌ์๋ยท์ด์ดํ๊ธฐยท์ถ๊ฐ ์คํ์ Controller ์ ์ฒด์ ์ ์ ์์ ๋๊ธฐ์ด์ ๊ณต์ ํฉ๋๋ค. 202๋ ์ ์ ์๋ฃ์ด๋ฉฐ ์ฆ์ ์คํ์ ๋ปํ์ง ์์ต๋๋ค. ์ฐจ๋ก๊ฐ ์ค๊ธฐ ์ ์๋ ์ฒซ Run๋ state: "queued", 0์ธ startedAt์ ์ ์งํ๋ฉฐ ์ฌ๋ฌ ์ ์ถ์ ์์ฝํ ์ ์์ต๋๋ค. ์ค์๊ฐ experiment์ ์ ํ ํ๋ queuePosition์ ์์ ์ ์ถ ์(ํ์ฐจ ์ ์๋)์ด๊ณ 0์ด๋ฉด ์๋ตํฉ๋๋ค. ๊ฐ์ ์ ์ถ์ ๋ฐ๋ณต์ ๋์ผํ ์์น๋ฅผ ์ฌ์ฉํ๋ฉฐ ๊ฒฐ๊ณผ manifest์๋ ์ ์ฅํ์ง ์์ต๋๋ค. ์คํจยท์ทจ์๋ ํด๋น ์ ์ถ์ ๋จ์ ๋ฐ๋ณต๋ง ๋๋ด๊ณ , ์ด์ Peer ์ ๋ฆฌ ํ์ธ ํ ๋ค์ ์ ์ถ์ ์์ํฉ๋๋ค. ์ ๋ฆฌ๊ฐ ์คํจํ๋ฉด ๋ค์ ์ ์ถ์ phaseName์ ์์ธ์ ํ์ํ๋ฉฐ ์๋ ์ฌ์๋ํฉ๋๋ค. ๊ทธ ๋๊ธฐ ํญ๋ชฉ์ ์ค์งํด๋ ์ดํ ์ ์ถ์ ์ ๋ฆฌ ์กฐ๊ฑด์ ์ ์ง๋ฉ๋๋ค. ๋จ์ผ Run์ด ์ ์งํ Peer๋ ๋ค์ ์ ์ถ ์ ์ ์ ๋ฆฌํฉ๋๋ค. ์์ฝ ๋๊ธฐ๋ phase๋ schedule ์๊ฐ์ ์๋ชจํ์ง ์์ต๋๋ค. Controller ์ฌ์์ ํ ๋จ์ ์์ฝ์ interrupted๋ก ํ์ํ๋ฉฐ ์๋ ๋ณต๊ตฌํฉ๋๋ค. ์คํ ์์ฝ์ ์ฐธ๊ณ ํ์ญ์์ค.
POST /api/v1/experiments๋ ์ฒซ run์ experiment ๊ฐ์ฒด์ 202๋ฅผ ๋ฐํํฉ๋๋ค. {scenario, repetitions, scenarioId?}๋ฅผ ์ ์ถํ๋ ค๋ฉด Content-Type: application/json์ ์ฌ์ฉํ์ญ์์ค. scenario๋ YAML ๋ฌธ์์ด์ด๋ฉฐ repetitions๋ฅผ ์๋ตํ๋ฉด ๊ธฐ๋ณธ๊ฐ์ 1์
๋๋ค. ์ ํ์ ์ธ scenarioId๋ ๊ทธ๋ฃน์ ์์ํ ์ ์ฅ ์๋๋ฆฌ์ค๋ฅผ ์๋ณํฉ๋๋ค. ๋ค๋ฅธ content type์ ์์ YAML๋ก ์ฒ๋ฆฌํฉ๋๋ค. ์์ YAML๊ณผ JSON์์ ํด์ํ scenario ๋ฌธ์์ด์ ํ๋๋ ๊ฐ๊ฐ 1 MiB์
๋๋ค. JSON ์์ฒญ ๋ณธ๋ฌธ์ escape๋ฅผ ๊ณ ๋ คํด 6 * 1 MiB + 64 KiB๊น์ง ํ์ฉํฉ๋๋ค. ์์ฒญ ๋ณธ๋ฌธ ์์ฒด๊ฐ ํ๋๋ฅผ ๋์ผ๋ฉด 413, ํด์ํ YAML ๋ฌธ์์ด์ด ํ๋๋ฅผ ๋๊ฑฐ๋ scenario/repetition์ด ์ ํจํ์ง ์์ผ๋ฉด 400์
๋๋ค.
scenarioId๋ ์๋ฌธ์ 16์ง์ 32์๋ก ๋ ์ ์ฅ ์๋๋ฆฌ์ค ID์
๋๋ค. Controller๋ ์ ์ถํ scenario ๋ณธ๋ฌธ์ ์คํํ๋ฏ๋ก ํธ์ง๊ธฐ์ ๋ฏธ์ ์ฅ ๋ณ๊ฒฝ๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ ๊ท ์ ์ ์ scenario:<scenarioId>์ ํ์ฌ ์์์ ์ฝ๊ณ batch:<newBatchId>์ ๋ณต์ฌํฉ๋๋ค. repetitions๊ฐ 1์ด์ด๋ ๋ฐฐ์น ํค๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์๋๋ฆฌ์ค์ ๊ทธ๋ฃน์ด ์๊ฑฐ๋ ID๋ฅผ ์๋ตํ๊ฑฐ๋ ์์ YAML๋ก ์ ์ถํ๋ฉด ๊ฒฐ๊ณผ๋ Ungrouped๊ฐ ๋ฉ๋๋ค. ์ดํ ์๋ณธ ์๋๋ฆฌ์ค๋ฅผ ์ด๋ยท์ญ์ ํด๋ ๋ณต์ฌํ ์์์ ๋ฐ๊พธ์ง ์์ต๋๋ค. ์ฌ์๋ยท์ด์ดํ๊ธฐยท์ถ๊ฐ ์คํ์ ๊ธฐ์กด ๊ฒฐ๊ณผ ์์์ ์ ์งํฉ๋๋ค. ์๋ชป๋ ID๋ 400, ์ ๊ท ์ ์ ์ ์ ์ฅ ์๋๋ฆฌ์ค๊ฐ ์์ผ๋ฉด 404์
๋๋ค. ์ ์ฅ ์๋๋ฆฌ์ค ์ฝ๊ธฐ ์ค๋ฅ์ ๊ทธ๋ฃน ์กฐํยท์ ์ฅ ์คํจ๋ 500, ์์ ๊ฐ์ ํ๋ ์ด๊ณผ๋ 400์ ๋ฐํํฉ๋๋ค. ์ด๊ธฐ ๊ทธ๋ฃน ์์์ ์คํ ์ ์ ํ์ ์ ์ ์ ์ฅํ๋ฏ๋ก ์ด ์ค๋ฅ๋ค์ ์คํ ์์ ์ ์ ์ ์๋ฅผ ๊ฑฐ๋ถํฉ๋๋ค.
Idempotency-Key๋ ํธํ์ฑ์ ์ํด ์ ํ ์ฌํญ์ด์ง๋ง ์๋ํ์์๋ ๊ณ ์ ํค(์ต๋ 128๋ฐ์ดํธ)๋ฅผ ์ง์ ํ๊ณ ์๋ต์ด ๋ถํ์คํ๋ฉด ๊ฐ์ ์๋๋ฆฌ์ค ๋ณธ๋ฌธยท๋ฐ๋ณต ์ยทscenarioId๋ก ์ฌ์ฌ์ฉํ์ญ์์ค. UI๋ session storage๋ก ์๋ ์ฒ๋ฆฌํฉ๋๋ค. ์ค๋ณต ์์ฒญ์ Controller ์ฌ์์ ๋๋ ์๋ณธ ์๋๋ฆฌ์ค ์ญ์ ํ์๋ ๊ธฐ์กด ์ ์ Run์ ๋ฐํํ๋ฉฐ ์ฌ์คํํ์ง ์์ต๋๋ค. ๊ทธ๋ฃน ์์์ ๋ค์ ์ํํ๊ฑฐ๋ ์ดํ ์๋์ผ๋ก ์ด๋ํ ๊ฒฐ๊ณผ ์์์ ๋ฎ์ด์ฐ์ง ์์ต๋๋ค. ๊ฐ์ ํค์ ๋ค๋ฅธ ์
๋ ฅ(scenarioId ๋ณ๊ฒฝ ํฌํจ)์ 409, ์๋ ๊ฒฐ๊ณผ๊ฐ ์ญ์ ๋ ํค๋ 410์
๋๋ค. ํค๋ฅผ ์๋ตํ๋ฉด ์ฑ๊ณตํ ์์ฒญ๋ง๋ค ์ ๋ฐฐ์น๋ฅผ ๋ง๋ญ๋๋ค. run-submissions/๋ฅผ ๋ฐฑ์
ํ์ญ์์ค.
์ต์ด ์ ์ถยท์ฌ์๋ยท์ด์ดํ๊ธฐยท์ถ๊ฐ ์คํ๋ง๋ค ์ executionId๋ฅผ ๋ถ์ฌํฉ๋๋ค. ํ์ฌ Run ๊ฐ์ฒด์ ๊ฐ์ X-KPL-Execution: <executionId>์ ๋ฃ์ด POST /api/v1/experiments/{id}/stop์ ํธ์ถํ์ญ์์ค. ๋ก๊ทธ์ธ๊ณผ X-KPL-Request: dashboard๋ ํ์ํฉ๋๋ค. ์คํ ID ๋๋ฝยท๋ถ์ผ์น์ ๊ณผ๊ฑฐ ๊ตฌ์ฑ์ ์ค์ง๋ 409์
๋๋ค. ๊ฐ์ ์คํ์ ๋ํด ์ ์๋ ์ค์ง๋ฅผ ๋ฐ๋ณตํด๋ ์์ ํ๋ฉฐ SSE์ stopRequested๋ก ์๋ก๊ณ ์นจ ํ์๋ ์ทจ์ ์งํ์ ํ์ธํฉ๋๋ค.
3ํ ๋ฐ๋ณต JSON ์์ฒญ ๋ณธ๋ฌธ ์์ :
{"scenario":"version: 1\nname: repeat-example\nphases:\n - action: wait\n duration: 1s\n","repetitions":3}๋ฐ๋ณต ์ ์ถ์ ๋งค iteration์ ๋ณ๋ run ID์ ๊ฒฐ๊ณผ ๊ธฐ๋ก์ ์์ฝํ๊ณ batchId, iteration, repetitions๋ฅผ ๊ณต์ ํฉ๋๋ค. ์์ฐจ ์คํํ๋ฉฐ ์คํจํ๊ฑฐ๋ ์ทจ์๋ iteration์ ๋๊ธฐ ์ค์ธ ๋๋จธ์ง ์คํ๋ ์ทจ์ํฉ๋๋ค. ํ์ฌ ์คํ ๋ฌถ์์ด ์งํ ์ค์ผ ๋ ํด๋น ๋ฌถ์์ ๊ตฌ์ฑ์์ ์ค์งํ๋ฉด ๊ทธ ์คํ ๋ฌถ์์ ์ทจ์ํฉ๋๋ค. repetitions > 1์์๋ ๋ง์ง๋ง์ ํฌํจํ ๋งค iteration์ด ์ต์ข
์ํ๋ฅผ ๊ธฐ๋กํ๊ธฐ ์ ์ Peer๋ฅผ fenceํ๊ณ ์ ๊ฑฐํฉ๋๋ค. ์์ฐ์ค๋ฝ๊ฒ ์ฑ๊ณตํ ๋จ์ผ ์คํ์ ์๋๋ฆฌ์ค ์ข
๋ฃ ์ ์คํ ์ค์ธ Peer๋ฅผ ์ ์งํ ์ ์์ต๋๋ค.
POST /api/v1/result-batches/{batchId}/retry๋ ์ ์ฅ๋ ๋ฏธ์๋ฃ ํ์ฐจ๋ฅผ ํ์ฐจ ์์๋๋ก ์๋ ์ฌ์คํํฉ๋๋ค. ์๋ฅผ ๋ค์ด 10ํ ์ค 4ํ์ฐจ๊ฐ ์คํจํ๋ค๋ฉด ์๋ฃ๋ 13ํ์ฐจ๋ ์ ์งํ๊ณ 410ํ์ฐจ๋ฅผ ๊ฐ ํ์ฐจ์ ์ฒซ phase๋ถํฐ ๋ค์ ์คํํฉ๋๋ค. ๋ค์ชฝ ํ์ฐจ ์ค ์ด๋ฏธ ์๋ฃ๋ ํ์ฐจ๋ ์ ์งํฉ๋๋ค. ์คํจยท์ค๋จ(์ฌ์์ ํ ๋ฏธ์์์ผ๋ก ๋จ์ ๊ธฐ๋ก ํฌํจ)ยท์ทจ์ ๊ธฐ๋ก์ ๋์์ผ๋ก ํฉ๋๋ค. ์๋๋ฆฌ์ค์ seed๋ฅผ ์ ์งํ๋ฉด์ ์ run ID๋ฅผ ๋ถ์ฌํ๋ฉฐ experiment/result ๋ฉํ๋ฐ์ดํฐ์ previousRunIds์ ์ด์ ์๋ ID๋ฅผ ๊ธฐ๋กํฉ๋๋ค. ๊ธฐ์กด ๋ก๊ทธ๋ Previous attempts์์ ๋ค์ด๋ก๋ํ ์ ์๊ณ , ํ์ฐจ๋ณ ๊ฐ์ฅ ์ต๊ทผ์ ์ ์ฅ๋ ์๋๋ง ๋ฐฐ์น ์งํ๋ฅ ๊ณผ ํ๊ท ์ ๋ฐ์ํฉ๋๋ค. ๊ธฐ์กด /resume์ ์๋ํ ํ์ฐจ๋ฅผ ๊ฑด๋๋ฐ๊ณ ๋ฏธ์์ ์์ฌ ํ์ฐจ๋ง ์ฌ๊ฐํฉ๋๋ค.
result-groups/{batchId}/batch.json์ ๋ชจ๋ ์ ์ ๋ชจ๋์ ํ์ ๊ฒฝ๊ณ์ด๋ฉฐ ID๋ฅผ ์ฌ์ฌ์ฉํ๋ ์ด์ดํ๊ธฐ์ ์ด์ ๋ฉํ๋ฐ์ดํฐ๋ ๋ณด์กดํฉ๋๋ค. ํ์ ์ ์ค๋จ์ ๋ถ๋ถ ์์ฝ์ ๋กค๋ฐฑํ๊ณ ํ์ ๋ ๋ฏธ์๋ฃ ์์
์ interrupted๋ก ๋จ๊น๋๋ค. superseded๋ก ์ต์ ๊ฒฐ๊ณผ๋ฅผ ์ญ์ ํด๋ ์ด์ ์๋๋ฅผ ์งํ๋ฅ ์ ๋ค์ ํฌํจํ์ง ์์ต๋๋ค. ์์๋ ๊ทธ๋ฃน ๊ธฐ๋ก์ ํด๋น ๊ทธ๋ฃน์ ์ฐจ๋จํ๊ณ ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๋ ๋ค๋ฅธ ๊ทธ๋ฃน์ Controller ์์์ ๊ณ์ํฉ๋๋ค.
๋ ์ด์ดํ๊ธฐ ๋ชจ๋๋ ์ ์ํ HTTP ์์ฒญ๊ณผ ๋
๋ฆฝ์ ์ผ๋ก Controller์์ ์คํํฉ๋๋ค. ์ ํ์ฐจ ์คํ ์ ์ ์ด์ Peer๋ฅผ fenceยท์ ๊ฑฐํ๊ณ Agent ์ํ๋ฅผ ๊ฐฑ์ ํฉ๋๋ค. ์ ๋ฆฌ๊ฐ ์คํจํ๊ฑฐ๋ ์ ๋ฆฌ ์ค ์ฌ์ฉ์๊ฐ ์ ์งํ๋ฉด ๋๊ธฐ ํ์ฐจ๋ฅผ canceled๋ก ๊ธฐ๋กํ๊ณ experiment ๋ฉํ๋ฐ์ดํฐ์ ์ด์ ๋ฅผ ๋จ๊ธฐ๋ฉฐ ์ ํ์ฐจ๋ ์์ํ์ง ์์ต๋๋ค. Agentยท์ ๋ฆฌ ์ค๋ฅ๋ฅผ ํด๊ฒฐํ ๋ค ๋ค์ ์ด์ดํ๊ธฐ๋ฅผ ์คํํ ์ ์์ต๋๋ค. ์คํยท์ต์ข
์ ๋ฆฌยท๋ค์ด๋ก๋ยท๊ฐ๋ณ ๋ฐ ๋ฐฐ์น ๋ถ์์ด ์งํ ์ค์ด๋ฉด ์ ์๋ฅผ ๊ฑฐ์ ํ๋ฉฐ, ์๋ฃ๋ ํ์ฐจ ๊ธฐ๋ก์ ๋ฎ์ด์ฐ์ง ์์ต๋๋ค.
cleanupState(pending, running, complete, failed, retained)์ dataState(pending, collecting, complete, incomplete, unverified)๋ ์คํ state์ ๋ณ๊ฐ์ด๋ฉฐ cleanupError, integrityError์ ๋ฌธ์ ๋ฅผ ๋ณด์กดํฉ๋๋ค. ์ Agent๋ runDrain์ ์๋ฆฌ๊ณ ๊ณผ๊ฑฐ Agent๋ฅผ ์ฌ์ฉํ Run์ unverified์
๋๋ค. ์์ธ ๊ฒฐ๊ณผ์ agents, controllerVersion์ ์คํ ํ๊ฒฝ์ด๋ฉฐ SSE์์๋ ํฐ ํ๊ฒฝ ๋ฐฐ์ด์ ์ ์ธํฉ๋๋ค. run-ownership/๋ create RPC ์ ์ ์ฐธ์ฌ Agent๋ฅผ ๊ธฐ๋กํ์ฌ Agent ์ฌ๋ฑ๋ก ์ ์๋ ์ ๋ฆฌ ๋์์ ์ ์งํฉ๋๋ค.
GET /api/v1/experiments, Dashboard snapshot/SSE์ ์ต์ด ์ ์ถ ์๋ต์ ์ค์๊ฐ experiment ๊ฐ์ฒด์๋ timing์ด ํฌํจ๋ ์ ์์ต๋๋ค. ํ๋๋ estimatedFinishAt(UTC), ์์๊ฐ ์๋ remainingSeconds, basis(scenario ๋๋ observed-runs), observedRuns, overdue์
๋๋ค. ์งํ ์ค์ธ ๋ฐ๋ณต Run์๋ batchEstimatedFinishAt, batchRemainingSeconds, batchOverdue๋ ํฌํจ๋ฉ๋๋ค(0ยทfalse์ธ ์ ํ ํ๋๋ ์๋ต ๊ฐ๋ฅ). ๋๊ธฐ Run์ ์ข
๋ฃ ์๊ฐ์๋ ๊ฐ์ ๋ฐฐ์น์ ์ ํ Run ์๊ฐ์ด ํฌํจ๋ฉ๋๋ค. ์๋ฃยท์คํจยท์ทจ์๋ Run์ด๋ ์๊ฐ ์ ๋ณด๊ฐ ๋ถ์กฑํ ๊ฒฝ์ฐ timing์ ์๋ตํ๋ฉฐ ๊ฒฐ๊ณผ manifest์ ์ ์ฅํ์ง ์์ต๋๋ค. ๊ณ์ฐ ๋ฐฉ์๊ณผ ๋ถํ์ค์ฑ์ ์์ ์ข
๋ฃ ์๊ฐ์ ์ฐธ๊ณ ํ์ญ์์ค.
์ค์ง endpoint๋ cleanup ์๋ฃ ์ , ์ทจ์ ์์ฒญ์ ์ ์ํ๋ฉด 202์ JSON {"runId":"run-id","status":"stopping"}์ ๋ฐํํฉ๋๋ค. Dashboard๋ snapshot์์ ์คํยท๋๊ธฐ ์ค์ธ ๊ตฌ์ฑ์์ด ์์์ ํ์ธํ ๋๊น์ง ํด๋น ์คํ ๋๋ ๋ฐฐ์น์ ๋ฒํผ์ **Stoppingโฆ**์ผ๋ก ๋นํ์ฑํํ๋ฉฐ, ์ ์ ์๋ต๋ง์ผ๋ก ๋ฒํผ์ ๋ค์ ํ์ฑํํ์ง ์์ต๋๋ค. /api/v1/experiments ๋๋ snapshot์์ ์ต์ข
์ํ๋ฅผ ํ์ธํ์ญ์์ค. ์ทจ์ handle์ด ๋ ์ด์ ์๋ run์ 404์
๋๋ค. ๊ฒฝ๋ยท๊ธฐ์กด ์คํธ๋ฆผ ๊ณ์ฝ์ Dashboard SSE๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค. /api/v1/events๋ ํ์ฌ Controller ์ํ์์ ๊ฐ์ฅ ์ต๊ทผ event ์ต๋ 300๊ฐ๋ฅผ ํฌํจํฉ๋๋ค.
์ ์ฅ์ ๋ฃจํธ์์ ์คํํฉ๋๋ค. ํธ์คํธ๋ access๊ฐ ํ์ํ Controller ์ฃผ์๋ก ๋ฐ๊พธ๊ณ , ๋จผ์ ์ธ์ฆ ์ ์ฐจ๋ก KPL_COOKIE_JAR๋ฅผ ์์ฑํ์ญ์์ค.
curl -X POST http://control-node:8080/api/v1/experiments \
-H 'Content-Type: application/yaml' \
-b "${KPL_COOKIE_JAR:?Log in first}" -H 'X-KPL-Request: dashboard' \
--data-binary @examples/smoke.yaml์๋๋ฆฌ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ endpoint๋ ์ฌ์ฌ์ฉํ ํธ์ง๊ธฐ ์ ๋ ฅ์ ์คํ ๊ฒฐ๊ณผ์ ๋ณ๋๋ก ์ ์ฅํฉ๋๋ค. ๋ชฉ๋ก์์๋ YAML์ ์ ์ธํ๊ณ , ๊ฐ๋ณ GETยทPOSTยทPUT ์๋ต์๋ ํฌํจํฉ๋๋ค. UI ์ฌ์ฉ ์์์ ์ ์ฅ ์์น๋ ์๋๋ฆฌ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์๋ด, payload์ ๊ฒ์ฆ ์ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ API๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค.
POST /api/v1/result-batches/{batchId}/append๋ ๋ก๊ทธ์ธ ์ธ์
, X-KPL-Request: dashboard, JSON {"additionalRuns":10,"expectedRepetitions":10}์ ์๊ตฌํฉ๋๋ค. ๋ ํ๋๋ ์์ ์ ์์ด๋ฉฐ ์ถ๊ฐ ํ ์ดํฉ์ 100 ์ดํ์ฌ์ผ ํฉ๋๋ค. ์ฑ๊ณตํ๋ฉด ์ฒซ ์ ๋๊ธฐ Run๊ณผ 202๋ฅผ ๋ฐํํฉ๋๋ค. ์์์์๋ iteration: 11, repetitions: 20์ด๋ฉฐ ๊ธฐ์กด ๋ฐฐ์น ID์ ์๋ฃ ๊ฒฐ๊ณผ๋ฅผ ์ ์งํฉ๋๋ค. ์คํ์ Controller ์๋ช
์ ์ฐ๊ฒฐํ์ฌ ์์ฒญยท๋ธ๋ผ์ฐ์ ์ข
๋ฃ๋ก ์ทจ์๋์ง ์์ต๋๋ค.
์ ์ ์ ๊ธ ์๋ ํ์ฌ ๊ทธ๋ฃน ์ดํฉ์ด expectedRepetitions์ ์ผ์นํด์ผ ํฉ๋๋ค. ๋์ยท์ค๋๋ ์ค๋ณต ์์ฒญ์ ๋ค์ ์ถ๊ฐํ์ง ์๊ณ 409๋ฅผ ๋ฐํํฉ๋๋ค. ๋๋ฝยท๋ฏธ์๋ฃยท๋ถ์ผ์น ํ์ฐจ, ์๋ก ๋ค๋ฅธ ์ ์ฅ ์๋๋ฆฌ์ค, ํ์ฑ ๋ฐฐ์นยท๋ค์ด๋ก๋ยท๋ถ์๋ 409์
๋๋ค. ์๋ชป๋ ๋ณธ๋ฌธยท์๋์ 400, ์๋ ๊ทธ๋ฃน์ 404, ๋ก์ปฌ ๊ณต๊ฐ ๋ถ์กฑ์ 507, ์ ์ฅ ์ค๋ฅ๋ 500์
๋๋ค. ์ ์ ์ฌ๋ถ๊ฐ ๋ถ๋ช
ํํ๋ฉด ๊ทธ๋ฃน์ ์๋ก๊ณ ์นจํ ๋ค ์ฌ์์ฒญํ์ญ์์ค. ํ์ ๋ ์ถ๊ฐ๋ ํ์ฌ ์ดํฉ๊ณผ ๋ฐฐ์น ๊ตฌ์ฑ ์๋ช
์ ๋ฐ๊พธ๋ฏ๋ก ๋ค์ ํตํฉ ๋ถ์์ ๊ธฐ์กดยท์ถ๊ฐ ์๋ฃ Run์ ํจ๊ป ์ง๊ณํฉ๋๋ค.
๋ก์ปฌ ๊ทธ๋ฃน ๊ธฐ๋ก์ด ์์์ ํ์ ๊ฒฝ๊ณ์
๋๋ค. ์ค๋น ์ค์ธ ์ถ๊ฐ๋ถ์ ์จ๊ธฐ๊ณ ๋ณต๊ตฌ ์ ๋กค๋ฐฑํ๋ฉฐ, ํ์ ๋ ๋๊ธฐ ํ์ผ์ ๊ธฐ์กด ์ฌ์๋ ์ ์ฐจ๋ก ์ฌ๊ฐํ ์ ์๋๋ก ๋ณด์กดํฉ๋๋ค. ๋ชฉ๋กยท์ ๋ถ์์ ๊ณผ๊ฑฐ ์๋ณธ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ฎ์ด์ฐ์ง ์๊ณ ํ์ฌ ์ดํฉ์ ์ ์ฉํฉ๋๋ค. ๋ ๊ฒฐ๊ณผ ์ ์ฅ์์ result-groups/<batchId>/batch.json์ ํจ๊ป ๋ฐฑ์
ํด์ผ ํฉ๋๋ค.
๊ฒฐ๊ณผ API๋ ์์ ์๊ฐ ์ต์ ์์ ์ ์งํ๋ queued์ฒ๋ผ ์์ ์๊ฐ์ด ๊ฐ์ผ๋ฉด ๋ฐฐ์นยทํ์ฐจยทID ์์๋ก ์ ๋ ฌํฉ๋๋ค.
์์ ์ด๋ฒคํธ์ ๊ด์ธก์ ๋ก์ปฌ <data-dir>/current-run/<run-id>/์ ๊ธฐ๋กํฉ๋๋ค. ๋ณด๊ด ์์
์๋ ๊ฒ์ฆํ ๋ก๊ทธ ์กฐ๊ฐ๊ณผ ํฐ ๊ฐ๋ณ ๋ถ์ ํ์ผ์ <data-dir>/runs/<run-id>/๋ก ์ฎ๊ธฐ๊ณ ์์ ๋ก์ปฌ ๋ฉํ๋ฐ์ดํฐ ์ธ๋ฑ์ค๋ฅผ ์ ์งํฉ๋๋ค. ๊ธฐ๋ณธ ๋ก์ปฌ data ๋๋ ํฐ๋ฆฌ๋ data์ด๋ฉฐ Swarm์ /var/lib/kpl/data์ ๋ง์ดํธํฉ๋๋ค. NAS์๋ runs/๋ง ๋ ์ ์์ต๋๋ค. ๋ณต์ฌยท๋ฆ์ ๋ก๊ทธยท๋ณต๊ตฌยท๋ฐฑ์
๊ท์น์ ๋ก์ปฌ ๊ธฐ๋ก๊ณผ NAS ๋ณด๊ด์ ์ฐธ๊ณ ํ์ญ์์ค.
๋์๋ณด๋์ Download results๋ก ์คํ ๊ฒฐ๊ณผ๋ฅผ ZIP์ผ๋ก ๋ฐ์ ์ ์์ต๋๋ค. Saved results์๋ ์ด์ Controller ์คํ์์ ๋ณด์กด๋ ๊ฒฐ๊ณผ๋ ํ์๋๋ฉฐ, Refresh๋ก ๋ชฉ๋ก์ ๋ค์ ์ฝ์ต๋๋ค. ์คํ ์ค ์คํ์ Download snapshot์ ๋ค์ด๋ก๋ ์์ ์์ ๊น์ง ์ ์ฅ๋ ๊ธฐ๋ก์ ๋ด์ต๋๋ค. ์ต๊ทผ 300๊ฐ ์ด๋ฒคํธ ๋ฒํผ์ ๋ณ๊ฐ๋ก ์ ์ฅ๋ ์ ์ฒด ์ด๋ฒคํธ ๋ก๊ทธ๋ฅผ ๋ด๋ณด๋ ๋๋ค. ํ์ผ ๊ตฌ์ฑ๊ณผ ์์ง ํ๊ณ๋ ์คํ ๊ฒฐ๊ณผ ๋ค์ด๋ก๋๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค.
GET /api/v1/results๋ ์ ์ฅ ๊ธฐ๋ก์ ๋ฐํํฉ๋๋ค. ๊ฒฐ๊ณผ ๋ชฉ๋ก์ sourceBytes๋ scenario.yaml, experiment.json, events.jsonl, observations.jsonl, ์ ํ์ note.json ์ ๋ก์ปฌ ํ์ผ๊ณผ ์ธ๋ฑ์ค์ ๋ฑ๋ก๋ NAS ๊ฐ์ฒด๋ฅผ ํฉํ ๋
ผ๋ฆฌ ํฌ๊ธฐ์
๋๋ค. NAS์ ์ ์ํ๊ฑฐ๋ ๋ก๊ทธ ๋ณธ๋ฌธ์ ์ฝ๊ณ ๋ถ์ยท์์ถํ์ง ์๊ณ ๋ก์ปฌ ํ์ผ ํต๊ณ์ ๋ณด๊ด ์ธ๋ฑ์ค๋ง ์กฐํํ๋ฏ๋ก ํฐ ๊ฒฐ๊ณผ๋ ์ฉ๋์ ๋น ๋ฅด๊ฒ ํ์ํฉ๋๋ค. ์์ฑ๋ ๋ถ์ ์บ์ยท์ด๋ฏธ์ง, ๋ค์ด๋ก๋ ์ ์์ฑํ๋ metrics.jsonยทexport.json, ํ์ผ์์คํ
ํ ๋น ์ค๋ฒํค๋๋ ์ ์ธํฉ๋๋ค. ๋ฉํ๋ฐ์ดํฐ๊ฐ ์์๋์ด๋ ์๋ณธ ํ์ผ ํฌ๊ธฐ๋ฅผ ์กฐํํ ์ ์์ผ๋ฉด ์ฉ๋์ ํ์ํฉ๋๋ค. ์๋ณธ ํ์ผ ์์ฒด์ ํต๊ณ๋ฅผ ์ฝ์ ์ ์์ผ๋ฉด sourceBytes๋ฅผ ์๋ตํ๊ณ ํ๋ฉด์๋ **Source ยท โ**๋ก ํ์ํฉ๋๋ค.
DELETE /api/v1/results/{id}๋ ๋ก์ปฌ ์ญ์ ์ ์ญ์ ํ์ ์ ์ฅ ์ฑ๊ณต ์ 204(NAS ํ์ผ์ ๋น๋๊ธฐ ์ญ์ ), ๊ฒฐ๊ณผ๊ฐ ์์ผ๋ฉด 404, ์คํยท๋ฐฐ์น๊ฐ ํ์ฑ ์ํ์ด๊ฑฐ๋ ์ค์ GET ๋ค์ด๋ก๋๊ฐ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฉ ์ค์ด๋ฉด 409๋ฅผ ๋ฐํํฉ๋๋ค. ๋ชฉ๋ก ์กฐํ๋ ๋ค์ด๋ก๋ ์ถฉ๋๋ก ์ฒ๋ฆฌํ์ง ์์ต๋๋ค. NAS ํ์ผ descriptor๋ฅผ ์ฌ๋ ์งง์ ๋ณดํธ ๊ตฌ๊ฐ์๋ 409๊ฐ ๊ฐ๋ฅํ๋ฉฐ HEAD๋ descriptor ์บก์ฒ ํ ์ด ๋ณดํธ๋ฅผ ํด์ ํฉ๋๋ค.
DELETE /api/v1/result-batches/{batchId}๋ ๋ก๊ทธ์ธ ์ธ์
๊ณผ ์ ํํ ๋ฐฐ์น ID๋ฅผ ์ฌ์ฉํฉ๋๋ค. ํ์ผ์ ์ญ์ ํ๊ธฐ ์ ์ ์ ์ฒด ๊ตฌ์ฑ์์ ๊ฒ์ฌํ๋ฉฐ ์คํยท์ ๋ฆฌ ์ค์ธ run์ด๋ ๊ตฌ์ฑ์์ ZIP ๋ค์ด๋ก๋๊ฐ ์์ผ๋ฉด 409๋ฅผ ๋ฐํํฉ๋๋ค. ์คํจยท์ทจ์ run์ ํฌํจํ ๋ชจ๋ ์ ์ฅ ๊ตฌ์ฑ์, ๊ฐ๋ณ ๋ถ์, ๋ณ๋ ํตํฉ ํ๊ท ์ ์ ๊ฑฐํฉ๋๋ค. ์ฑ๊ณต ์ 200๊ณผ {"deletedIds":["run-id", "..."]}๋ฅผ ๋ฐํํ๋ฉฐ ๊ทธ๋ฃน์ด ์์ผ๋ฉด 404์
๋๋ค. ์๋ณธ ์์ด ๋จ์ ํตํฉ ํ๊ท ๋ ์ ๊ฑฐํ ์ ์์ต๋๋ค. ์ ์ฅ ์ฅ์น ์ค๋ฅ๋ 500์ด๋ฉฐ ์ผ๋ถ ์ญ์ ๊ฐ ๋๋ฌ์ ์ ์์ผ๋ฏ๋ก ๋ชฉ๋ก์ ๊ฐฑ์ ํ๊ณ ์ ์ฅ ์ค๋ฅ๋ฅผ ํด๊ฒฐํ ๋ค ์ฌ์๋ํ์ญ์์ค. ๋ธ๋ผ์ฐ์ ๋ ์์ฒญ์ 30์ด ์ ํ ์๊ฐ์ ์ ์ฉํ๋ฉฐ ๊ทธ ์ดํ์๋ Controller์์ ์๋ฃ๋ ์ ์์ต๋๋ค.
๋์๋ณด๋๋ ์ฉ๋ ํ์๋ฅผ ์ํ HEAD ์์ฒญ์ด๋ ZIP ํฌ๊ธฐ ์ฌ์ธก์ ํ์ด๋จธ๋ฅผ ์คํํ์ง ์์ต๋๋ค. ์ง์ ํธ์ถํ๋ HEAD /api/v1/experiments/RUN_ID/download๋ ๊ธฐ์กด์ฒ๋ผ ZIP encoder๋ฅผ ๋ฐ์ดํธ counter์ ์คํํ์ฌ ์ ํํ Content-Length๋ฅผ ๋ฐํํ๋ฉฐ, ๊ฐ๋ณ GET ๋ค์ด๋ก๋๋ ํด๋น ์ธก์ ์ ์ฌ์ฉํฉ๋๋ค. ์ผ๊ด ๋ค์ด๋ก๋๋ ํฌ๊ธฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ณ์ฐํ์ง ์๊ณ ์ ์กํฉ๋๋ค. ZIP์ ๋ฉ๋ชจ๋ฆฌ๋ ๋์คํฌ์ ํต์งธ๋ก ๋ณด๊ดํ์ง ์๊ณ ์คํธ๋ฆฌ๋ฐํฉ๋๋ค. ๊ฐ์ run์ ๋์ ์ธก์ ์ ๊ณต์ ํ๊ณ ์๋ก ๋ค๋ฅธ run์ ์ธก์ ์ ์ต๋ ๋ ๊ฐ๋ก ์ ํํฉ๋๋ค. ๊ธฐ์กด API ํธํ์ฑ์ ์ํด ๋ชฉ๋ก์ ์ค๋น๋ ZIP ํฌ๊ธฐ๊ฐ ์ ํจํ๋ฉด downloadBytes๋ ์ ๊ณตํ์ง๋ง ํ๋ฉด์ ์ด๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค.
Pending publication์ด ์์ผ๋ฉด ํ์ผ๊ณผ ์ํ๊ฐ ๊ฐ์ ๋์ ์ธก์ ํ ๋ฐ์ดํธ ์๋ฅผ ์ ์งํ๋ฉด์ HEAD ๋๋ ๋ค์ด๋ก๋๋ง๋ค ์ ๋ฐ๋๋ฅผ ์ ์งํ ์ export ์๊ฐ์ ๊ธฐ๋กํฉ๋๋ค. ์ ์ฅ ๋ฐฉ์์ด ๊ณ ์ ๋ export.json์๋ ๊ณ ์ ํญ ์๊ฐ ๋ฌธ์์ด์ ์ฌ์ฉํ๋ฏ๋ก ์๊ฐ์ด ๋ฐ๋์ด๋ ์ธ์ฝ๋ฉ ๊ธธ์ด๋ ๊ฐ์ต๋๋ค. Stable ๋ชฉ๋ก ํ์๋ downloadSizeMaxAgeMs๊ฐ ์๊ณ stable HEAD ์๋ต์๋ X-KPL-Result-Size-Max-Age-Ms๊ฐ ์์ต๋๋ค. Pending publication์ด ์์ผ๋ฉด ๋ฐ์ดํธ ์์ export ๊ฒฝ๊ณ๋ฅผ ์งง๊ฒ ํจ๊ป ์ฌ์ฌ์ฉํฉ๋๋ค. ๋ชฉ๋ก ํ์ downloadSizeMaxAgeMs๋ฅผ ํฌํจํ๊ณ HEAD๋ X-KPL-Result-Size-Max-Age-Ms๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ ๊ฐ์ ์๋ฒ์ ๋จ์ cache ์ ํจ ์๊ฐ์์ ์๋ต ์์ ์ฌ์ 1์ด๋ฅผ ๋บ ์์ ๋ฐ๋ฆฌ์ด์ด๋ฏ๋ก client์ server์ ์๊ณ๊ฐ ์ผ์นํ์ง ์์๋ ๋ฉ๋๋ค. ์ค๋น๋ ๊ฐ์ ์ฒ์ ํ์ธํ ๋ชฉ๋ก๋ง ์ ํจ ์๊ฐ์ ํ ๋ฒ ์ฐ์ฅํ๊ณ , ์ฐ์ฅํ ๊ฒฝ๊ณ์์ ๊ณ์ฐํ max age๋ฅผ ์๋ตํ๋ฏ๋ก ๋ฐ๋ก ์ด์ด์ง๋ GET์ด ํ์ ํฌ๊ธฐ์ ์ผ์นํฉ๋๋ค. ๋ชฉ๋ก์ ๋ฐ๋ณตํด์ ์๋ก๊ณ ์นจํด๋ deadline์ด ๊ณ์ ๋ฐ๋ฆฌ์ง๋ ์์ต๋๋ค. ์์ ์ฌ์ ๋ฅผ ์ ์ธํ๊ณ ๋จ์ ์ ํจ ์๊ฐ์ด ์์ผ๋ฉด ๋ชฉ๋ก์ downloadBytes์ downloadSizeMaxAgeMs๋ฅผ ๋ชจ๋ ์๋ตํ๊ณ , HEAD๋ ์๋ต ์ ์ ์ ๊ฒฝ๊ณ๋ฅผ ์ธก์ ํฉ๋๋ค.
Controller ์์ ํ ์ฒซ HEAD๋ ์๋ณธ ํ์ผยท์ํ ๋ณ๊ฒฝ ๋ค์๋ ์บก์ฒํ ํ์ผ์ ์ฝ๊ณ ์งํ๋ฅผ ๋ค์ ๊ตฌ์ฑํด์ผ ํ๋ฉฐ, pending ๊ฒฐ๊ณผ๋ ์งง์ cache๊ฐ ๋ง๋ฃ๋ ๋ค ์ด ์์ ์ ๋ฐ๋ณตํฉ๋๋ค. ์ธก์ slot ๋๊ธฐ, ์๋ณธ ๋ก๊ทธ ์ฝ๊ธฐ์ ์ฌ๊ตฌ์ฑํ ์งํ ์ง๊ณ ๋จ๊ณ์์ HTTP ์์ฒญ ์ทจ์๋ฅผ ํ์ธํ๋ฉฐ, ์ทจ์๋ ์์ฒญ์ server error ์๋ต ์์ด ์ค๋จํฉ๋๋ค. ์ ์ฅํ ์ด๋ฒคํธ ๋ก๊ทธ๊ฐ ํฌ๋ฉด ์ธก์ ์๊ฐ์ด ๊ธธ์ด์ง ์ ์์ต๋๋ค. ์ด ๋น์ฉ์ ์ง์ ์์ฒญํ HEAD๋ ์ค์ ๋ค์ด๋ก๋์๋ง ๋ฐ์ํ๋ฉฐ, ํ๋ฉด์ ์๋ณธ ์ฉ๋ ํ์์๋ ํ์ํ์ง ์์ต๋๋ค.
ZIP ์๋ณธ ๋ณต์ฌ๋ ์คํธ๋ฆฌ๋ฐํ๋ฉฐ ์งํ ์ฌ๊ตฌ์ฑ์๋ ๊ณ ์ ์ด๋ฒคํธ IDยท๋ฉ์์ง/์์ ์์ ๋น๋กํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
POST /api/v1/downloads๋ {"kind":"scenarios","ids":["scenario-id"]} ๋๋ {"kind":"results","ids":["run-id"]}๋ฅผ ๋ฐ์ต๋๋ค. ๊ฒฐ๊ณผ ID๋ ๋ฐฐ์น ๊ตฌ์ฑ์์ ํฌํจํ ๊ฐ๋ณ Run ID์ด๋ฉฐ ๋์๋ณด๋๊ฐ ์ ํํ ๋ฐฐ์น๋ฅผ Run ๋ชฉ๋ก์ผ๋ก ํ์ฅํด ์ ์กํฉ๋๋ค. ์ผ๋ฐ ๋ก๊ทธ์ธ ์ธ์
๊ณผ X-KPL-Request: dashboard๊ฐ ํ์ํฉ๋๋ค. ์์ฒญ๋น ID 1~2,000๊ฐ, JSON ๋ณธ๋ฌธ 512 KiB๊น์ง ํ์ฉํ๋ฉฐ ์ค๋ณต ID๋ ์ ๊ฑฐํฉ๋๋ค. ๊ฒ์ฆ์ ๋ก์ปฌ ๋ฉํ๋ฐ์ดํฐ๋ง ์ฝ๊ณ ๋ณด๊ด๋ ์๋ณธ ๋ก๊ทธ๋ ์ด์ง ์์ต๋๋ค.
์ฑ๊ณตํ๋ฉด 201๊ณผ {"url":"/api/v1/downloads/<ticket>","count":1,"expiresAt":"<UTC timestamp>"}๋ฅผ ๋ฐํํฉ๋๋ค. ์๋ชป๋ ์ ํ์ 400, ์๋ ํญ๋ชฉ์ 404, ์ฝ์ ์ ์๋ ๋ฉํ๋ฐ์ดํฐ๋ 500, ๋๊ธฐ ํฐ์ผ ์ ์ฅ์๊ฐ ๊ฐ๋ ์ฐจ๋ฉด 429์
๋๋ค. ํฐ์ผ์ 10๋ถ ๋ค ๋ง๋ฃ๋๊ณ ๋ฉ๋ชจ๋ฆฌ์๋ง ๋ณด๊ดํ๋ฏ๋ก Controller ์ฌ์์ ์ ๋ฌดํจํ๋ฉ๋๋ค. ๋๊ธฐ ํฐ์ผ์ ์ต๋ 16๊ฐ์
๋๋ค.
๋ก๊ทธ์ธ ์ํ์์ ๋ฐํ๋ URL๋ก GETํ๋ฉด ํฐ์ผ์ ์๋ชจํ๊ณ scenarios-<UTC timestamp>.zip ๋๋ results-<UTC timestamp>.zip ์ฒจ๋ถ ํ์ผ์ ์คํธ๋ฆฌ๋ฐํฉ๋๋ค. ์ ์ฒด ZIP์ ๋ธ๋ผ์ฐ์ JavaScript๋ ์๋ฒ์ ๋ณด๊ดํ์ง ์๊ณ ์ฌ์ ZIP ํฌ๊ธฐ ๊ณ์ฐ๋ ํ์ง ์์ต๋๋ค. ์ผ๊ด ์ ์ก์ ์ต๋ ๋ ๊ฐ๋ฅผ ๋์์ ์ฒ๋ฆฌํ๋ฉฐ, ์ด๊ณผ GET์ ํฐ์ผ์ ์๋ชจํ์ง ์๊ณ 429์ Retry-After: 5๋ฅผ ๋ฐํํฉ๋๋ค. ๋ง๋ฃยท์๋ชจ๋์๊ฑฐ๋ ์๋ ํฐ์ผ์ 410์
๋๋ค. ๋ค์ด๋ก๋ URL์ ์ธ์ฆ์ ๋์ ํ์ง ์์ผ๋ฉฐ HEAD๋ ์ง์ํ์ง ์์ต๋๋ค.
์๋๋ฆฌ์ค ํญ๋ชฉ์๋ ์ ์ฅ๋ YAML ์๋ฌธ์ ๋ด์ต๋๋ค. ๊ฒฐ๊ณผ ํญ๋ชฉ์๋ ๊ฐ๋ณ Run ZIP์ ๋ด์ผ๋ฉฐ ๊ฐ Run ์ฒ๋ฆฌ ์ฐจ๋ก์ ์ค๋
์ท์ ํ๋ณดํฉ๋๋ค. ํฐ์ผ์ ๋ชจ๋ ์๋ณธ์ ๋ฏธ๋ฆฌ ๋ณดํธํ์ง ์์ผ๋ฏ๋ก ์ฒ๋ฆฌ ์ ยท๋์ค์ ์ญ์ ๋ ์ ์ฅ์ ์ค๋ฅ๋ก ์ ์ก์ด ์คํจํ ์ ์์ต๋๋ค. ZIP ์ถ๋ ฅ์ ์์ํ๊ธฐ ์ ์๋ ๋๋ฝ ์ 404, ์ฝ๊ธฐ ์คํจ ์ 500์ ๋ฐํํฉ๋๋ค. ์์ํ ๋ค์๋ ์คํธ๋ฆผ์ ์ค๋จํ๊ณ ์์ฑ๋ ๋ฐ๊นฅ ZIP์ ๋จ๊ธฐ์ง ์์ต๋๋ค. ์ทจ์ ์ ํ์ฌ Run์ ๋ค์ด๋ก๋ ๋ณดํธ์ ์ ์ก ์ฌ๋กฏ์ ํด์ ํฉ๋๋ค. ํ์ผ๋ช
๊ณผ ๊ตฌ์ฑ์ ์๋๋ฆฌ์ค ๋ค์ด๋ก๋, ๊ฒฐ๊ณผ ๋ค์ด๋ก๋๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค.
๋ก๊ทธ์ธ์ด ํ์ํ GET /api/v1/result-storage๋ localDirectory, archiveDirectory, availableBytes, minFreeBytes, checking, checkStartedAt, lastCheckedAt, phase, lastProgressAt, stalled, ์ ํ์ error๋ฅผ ๋ฐํํฉ๋๋ค. ๊ณต๊ฐ์ Controller์ ๋ก์ปฌ ๋ฐ์ดํฐ ํ์ผ์์คํ
์์ ์ธก์ ํ๊ณ NAS ์ํ๋ ์ต๊ทผ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
๊ฒฐ๊ณผ์ด๋ฏ๋ก ์์ฒญ์ด NAS ์กฐํ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์์ต๋๋ค. phase๋ preparing, discovering, copying, verifying, publishing, deleting, ์คํ ์ค ๋๊ธฐ์ธ paused, idle์ ๊ตฌ๋ถํฉ๋๋ค. ์๋ฒ๋ ์์นด์ด๋ธ I/O ๋จ๊ณ์์ ์งํ ๊ธฐ๋ก์ด 15์ด ๋๊ฒ ๊ฐฑ์ ๋์ง ์์ ๋๋ง stalled๋ฅผ ์ค์ ํฉ๋๋ค. ์ ์ฒด ์์
์๊ฐ, ๋ก์ปฌ ์ค๋น, ์๋์ ์ธ ์คํ ๋๊ธฐ๋ ์ง์ฐ ํ์ ์์ ์ ์ธํฉ๋๋ค. ๋ณต์ฌยท๊ฒ์ฆ์ ์ฒญํฌ ์๋ฃ๋ง๋ค ์งํ ์๊ฐ์ ๊ฐฑ์ ํ๊ณ ๋๊ธฐ ํ ์ฌ๊ฐํ ๋ ํ์ด๋จธ๋ฅผ ์๋ก ์์ํฉ๋๋ค. UI๋ ์๋ฒ ํ์ ์ ์ฌ์ฉํ๋ฏ๋ก ๋ธ๋ผ์ฐ์ ์๊ณ ์ฐจ์ด๋ก ๊ฒฝ๊ณ ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค. ์งํ ์ง์ฐ ํ์์ด๋ฉฐ NAS ์ฑ๋ฅ ์ธก์ ์ด๋ ์๋ ์์
์ทจ์๋ฅผ ์๋ฏธํ์ง ์์ต๋๋ค. ๋์๋ณด๋๋ ํ๋ฉด์ด ๋ณด์ผ ๋ SSE์ ๋ณ๋๋ก ์ด ์์ endpoint๋ฅผ 15์ด๋ง๋ค ์กฐํํฉ๋๋ค.
๊ฒฐ๊ณผ ํ์๋ local, pending, archiving, archived ์ค ํ๋์ธ storage: {state, error?, updatedAt}๋ฅผ ํฌํจํฉ๋๋ค. ์ ์ฅ ์ํ๋ ์คํ ์ํ๋ ๋ฐฐ์น ํ๊ท ๊ตฌ์ฑ์ ๋ฐ๊พธ์ง ์์ต๋๋ค. sourceBytes๋ NAS ๋ก๊ทธ ์กฐ๊ฐ๊ณผ ๋ก์ปฌ ํ์ ๊ธฐ๋ก์ ๊ฐ๊ฐ ํ ๋ฒ๋ง ์
๋๋ค. ๋ณด๊ดํ ์๋ณธ ๋ค์ด๋ก๋ยท๋ถ์์๋ NAS ์๋ต์ด ํ์ํ์ง๋ง ๋ชฉ๋กยท๋ฉ๋ชจ๋ ๋ก์ปฌ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๊ธฐ์กด NAS ๊ฒฐ๊ณผ๋ ์์ ์ยท์ฃผ๊ธฐ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ธ๋ฑ์ค๊ฐ ๋ฐ๊ฒฌํ๋ฉด์ ํ๋ฉด์ ๋ํ๋ฉ๋๋ค.
์ POST /api/v1/experiments ์์ฒญ์ ๋ก์ปฌ ์ฌ์ ๊ฐ ์ค์ ๊ธฐ์ค๋ณด๋ค ์์ผ๋ฉด 507์
๋๋ค. ๋ฐ๋ณตยท์ฌ๊ฐ ๋ฐฐ์น๋ ๋ค์ Run ์ ์ phaseName: "Waiting for local result storage"์ธ ๋๊ธฐ ์ํ๊ฐ ๋ ์ ์์ผ๋ฉฐ ์ทจ์ํ ์ ์์ต๋๋ค. ํ์ค CLI ๊ธฐ๋ณธ๊ฐ์ --run-min-free-bytes / KPL_RUN_MIN_FREE_BYTES์ 1 GiB์ด๊ณ 0์ด๋ฉด ์ฌ์ ๊ณต๊ฐ ๊ฒ์ฌ๋ฅผ ๋๋๋ค. ํ์ฑ Run์์๋ ์ฝ 1์ด๋ง๋ค ๊ณต๊ฐยท๊ธฐ๋ก ์ค๋ฅ๋ฅผ ํ์ธํ๋ฉฐ ๋ฌธ์ ๋ฐ์ ์ ๋ฐ์ดํฐ ๋ถ์์ ์ ํ์ํ๊ณ ์คํยท๋๊ธฐ ํ์ฐจ๋ฅผ ์ค๋จํฉ๋๋ค. ์ด ๊ธฐ์ค์ ํฌ๊ธฐ๊ฐ ์ ํด์ง์ง ์์ ํ์ฑ Run์ ์ ์ฒด ๊ณต๊ฐ์ ์์ฝํ์ง๋ ์์ต๋๋ค.
GET /api/v1/results/{id}/note๋ Cache-Control: no-store์ {runId, text, revision, updatedAt?}๋ฅผ ๋ฐํํฉ๋๋ค. ๋ฉ๋ชจ๊ฐ ์์ผ๋ฉด text๋ ๋น ๋ฌธ์์ด, revision์ "0"์ด๋ฉฐ ์๊ฐ์ ์๋ตํฉ๋๋ค. ์กฐํยท์ ์ฅ ๋ชจ๋ ๋ก๊ทธ์ธ ์ธ์
์ด ํ์ํฉ๋๋ค. PUT์ X-KPL-Request: dashboard์ ๋ง์ง๋ง ์กฐํ์์ ๋ฐ์ revision์ ํฌํจํ JSON {text, revision}์ ์๊ตฌํฉ๋๋ค. ์ฑ๊ณตํ๋ฉด 200๊ณผ ์ ์ฅ ๋ ์ฝ๋๋ฅผ ๋ฐํํ๋ฉฐ ๋ด์ฉ์ด ๋ฐ๋๋ฉด ์ ๋ถํฌ๋ช
revision์ ๋ฐ๊ธํฉ๋๋ค. updatedAt์ UTC RFC 3339 ์๊ฐ์
๋๋ค. ์ค๋๋ revision์ 409๋ฅผ ๋ฐํํ๋ฏ๋ก ์ต์ ๋ด์ฉ์ ์กฐํยท๊ฒํ ํ ํ ๋ค์ ์ ์ถํ์ญ์์ค. ๋ฉ๋ชจ๋ ์ธ์
๋ณ ๋น๊ณต๊ฐ ๋ฐ์ดํฐ๊ฐ ์๋ ๊ณต์ ๊ธฐ๋ก์
๋๋ค.
๋ณธ๋ฌธ์ ๋์ฝ๋ฉ๋ UTF-8 ๊ธฐ์ค ์ต๋ 16,384๋ฐ์ดํธ์
๋๋ค. ๊ณต๋ฐฑ๋ง ์
๋ ฅํ๋ฉด ๋ฉ๋ชจ๋ฅผ ๋น์ฐ๊ณ , ๊ทธ ์ธ์๋ ๊ณต๋ฐฑ๊ณผ ์ค๋ฐ๊ฟ์ ๋ณด์กดํฉ๋๋ค. ํ์ ํ๋ ๋๋ฝ/null, ์ ์ ์๋ ํ๋, ํํ JSON๊ณผ ๋ณธ๋ฌธ ์ฉ๋ ์ด๊ณผ๋ 400์
๋๋ค. JSON ์ด์ค์ผ์ดํ์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ณ ๋ คํด ์์ฒญ ์ ์ฒด๋ 6 * 16,384 + 4,096๋ฐ์ดํธ๊น์ง ํ์ฉํ๋ฉฐ ์ด๊ณผ ์ 413์
๋๋ค. ์๋ชป๋๊ฑฐ๋ ์๊ฑฐ๋ ์ญ์ ๋ run ID๋ 404์
๋๋ค. ์ ์ฅ์ ์ค๋ฅ๋ 500์ด๋ฉฐ ์ฝ์ ์ ์๋ ๊ธฐ์กด ๋ฉ๋ชจ๋ฅผ ์์๋ก ๊ต์ฒดํ์ง ์์ต๋๋ค. ๋ด์ฉ์ด ๊ฐ์ผ๋ฉด revision๊ณผ ์ ์ฅ ์๊ฐ์ ์ ์งํฉ๋๋ค.
Controller๋ ๊ฒฐ๊ณผ ์ญ์ ์ ๋์ผํ ์ ์ฅ ์ ๊ธ ์๋ ๋ก์ปฌ current-run/<run-id>/note.json์ ์์์ ์ผ๋ก ๊ต์ฒดํฉ๋๋ค. ๋ณด๊ด ์์
์๋ ์ด ์ ๊ธ ๋ฐ์์ runs/<run-id>/note.json์ ๋น๋๊ธฐ ๋ฐ์ํฉ๋๋ค. ๋น์ด ๋ฉ๋ชจ๋ revision์ ์ ์งํ์ฌ ์ค๋๋ ํธ์ง์ผ๋ก ๋ด์ฉ์ด ๋ณต์๋์ง ์๊ฒ ํฉ๋๋ค. ๊ธฐ์กด ๊ฒฐ๊ณผ๋ฅผ ๋ง์ด๊ทธ๋ ์ด์
ํ ํ์๊ฐ ์๊ณ ์คํ ๋ฉํ๋ฐ์ดํฐ๋ ๋ถ์ ์บ์๋ฅผ ๋ค์ ์ฐ์ง ์์ต๋๋ค. ์คํยท๋ค์ด๋ก๋ ๋์ค์๋ ์์ ํ ์ ์์ผ๋ฉฐ ์ด๋ฏธ ์บก์ฒํ ZIP์ ๋น์ ๋ฉ๋ชจ ๋ฒ์ ์ ์ ์งํฉ๋๋ค. GET /api/v1/results๋ ๋น์ด ์์ง ์์ ๋ฉ๋ชจ์ ์ ํ์ note: {preview, updatedAt}๋ฅผ ์ถ๊ฐํฉ๋๋ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ ๊ณต๋ฐฑ์ ์ ๋ฆฌํ๊ณ Unicode ์ฝ๋ ํฌ์ธํธ 160๊ฐ์ ๋ง์ค์ํ๋ก ์ ํํ๋ฏ๋ก ์ ์ฒด ๋ณธ๋ฌธ์ ๊ฐ๋ณ ๋ฉ๋ชจ API๋ก ์กฐํํ์ญ์์ค. ๋์๋ณด๋ SSE์๋ ๋ฉ๋ชจ๊ฐ ๋ค์ด๊ฐ์ง ์์ต๋๋ค.
GET / PUT /api/v1/result-batches/{batchId}/note๋ ๊ฐ์ ํฌ๊ธฐ ์ ํยทrevisionยท์ํ ์ฝ๋ยท๋ก๊ทธ์ธ/CSRF ๊ท์น์ ์ ์ฉํ๋ฉฐ {batchId, text, revision, updatedAt?}๋ฅผ ๋ฐํํฉ๋๋ค. ์ ์ฅ๋ ๊ตฌ์ฑ์์ด๋ ๊ธฐ์กด ๊ทธ๋ฃน ๋ฉํ๋ฐ์ดํฐ ๋๋ ํฐ๋ฆฌ๊ฐ ์์ด์ผ ํฉ๋๋ค. Group ๋ฉ๋ชจ๋ ๋ก์ปฌ result-groups/<batchId>/note.json์ ์ ์ฅํ์ฌ ์ฌ์๋ยท๊ฐ๋ณ Run ์ญ์ ยท๋ถ์ ๊ฐฑ์ ์ผ๋ก ๋ฎ์ด์ฐ์ง ์์ต๋๋ค. ๊ทธ๋ฃน ์ ์ฒด ์ญ์ ๋ ๋ชจ๋ ๊ตฌ์ฑ์ ์ญ์ ๊ฐ ์ฑ๊ณตํ ๋ค ๋ฉ๋ชจ๋ฅผ ์ ๊ฑฐํ๋ฉฐ, ๊ตฌ์ฑ์์ด ๋ชจ๋ ์ญ์ ๋ ๋ฉ๋ชจ๋ ๊ทธ๋ฃน ์ญ์ API๋ก ์ ๋ฆฌํ ์ ์์ต๋๋ค. ์ค๋๋ ํธ์ง์ฐฝ์์ ์ ์ฅํด๋ ์ญ์ ๋ ๊ทธ๋ฃน์ ์ฌ์์ฑํ์ง ์์ต๋๋ค.
๋ชฉ๋ก ์๋ต์ ๊ฐ์ ๋ด์ฉ์ ๋ฐ๋ณตํ์ง ์๋๋ก ๊ทธ๋ฃน ๊ตฌ์ฑ์ ์ค ์ต๋ ํ๋์ groupNote: {preview, updatedAt}๋ฅผ ํฌํจํฉ๋๋ค. ํด๋ผ์ด์ธํธ๋ batchId๋ก ๋ฌถ์ ๋ค ํ์ํด์ผ ํฉ๋๋ค. ์ ์ฒด Group ๋ฉ๋ชจ๋ ํธ์ง ์์๋ง ์กฐํํ๊ณ SSE์ ๊ฐ๋ณ Run ZIP์ ํฌํจํ์ง ์์ต๋๋ค. NAS Run ๋ณด๊ด์์๋ ๋ฐ์ํ์ง ์์ผ๋ฏ๋ก result-groups/๋ฅผ ๋ก์ปฌ Controller ๋ฐ์ดํฐ์ ํจ๊ป ๋ฐฑ์
ํ์ญ์์ค.
์ ์ฅ ์คํ ํ๋๋ฅผ ๋ถ์ํ๋ ค๋ฉด POST /api/v1/analysis-jobs/{id}๋ก ์ ์ํ๊ณ ๊ฐ์ ๊ฒฝ๋ก์ GET์ผ๋ก ์ํ๋ฅผ ํ์ธํฉ๋๋ค. POST์ GET/HEAD ๋ชจ๋ ๋ก๊ทธ์ธ ์ธ์
์ด ํ์ํฉ๋๋ค. ์ ์๋ ๋๊ธฐยท์คํ ์์
์ 202, ํ์ฌ ๋ฒ์ ์ ์๋ฃ ๊ฒฐ๊ณผ๋ฅผ ์ฌ์ฌ์ฉํ๋ฉด 200์
๋๋ค. Controller ์ ์ฒด์์ ๋๊ธฐยท์คํ ์์
์ ์ต๋ 32๊ฐ ์ ์ํ๊ณ (๊ฐ๋ ์ฐจ๋ฉด 503), ๊ณต์ ๋ถ์ ์ฌ๋กฏ์ ํ ๋ฒ์ ํ๋์ run์ ๋ถ์ํฉ๋๋ค. ํด๋ผ์ด์ธํธ๋ฅผ ๋ซ์๋ ์ ์๋ ์์
์ ์ทจ์๋์ง ์์ต๋๋ค.
ํ๋์ run ์์์๋ ๋
๋ฆฝ๋ ๊ด์ธก ์ค๋
์ท์ ๊ทธ๋ํ ๋ฉํธ๋ฆญ์ ๋ณ๋ ฌ๋ก ๊ณ์ฐํฉ๋๋ค. worker ์๋ min(4, max(1, GOMAXPROCS - 1))์ด๋ฉฐ ์ฌ๋ฌ CPU๋ฅผ ์ฌ์ฉํ๋ Controller์์๋ Go ์คํ ์ฌ๋กฏ ํ๋๋ฅผ ์ฌ์ ๋ก ๋จ๊น๋๋ค. ๊ฐ์ ๊ทธ๋ํ๋ ์งํ ์ค์ธ ๊ณ์ฐ๊ณผ ์บ์๋ฅผ ๊ณต์ ํ๋ฉฐ ์ต๋ 256๊ฐ๋ฅผ ๋ณด์กดํฉ๋๋ค. ๊ฒฐ๊ณผ๋ ์๋ ๊ด์ธก ์์๋ฅผ ์ ์งํ๊ณ , phase: graph metrics ์๋ฃ/์ ์ฒด๋ ๊ณ์ฐ์ด ๋๋ ๊ด์ธก ์๋ฅผ ํ์ํฉ๋๋ค. ์ค๋ฅ๋ ์ทจ์๊ฐ ๋ฐ์ํ๋ฉด ๋จ์ worker๋ฅผ ์ค๋จํ๊ณ ์ข
๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฝ๋๋ค. ๋ฉํธ๋ฆญ ์ ์์ ์บ์ ๋ถ์ ๋ฒ์ ์ ์ ์งํ๋ฉฐ, ๊ฐ๋ณยท๋ฐฐ์นยท๋๊ธฐ ๋ถ์์ ๋ชจ๋ ๊ฐ์ ๊ณ์ฐ ๊ฒฝ๋ก๋ฅผ ์ ์ฉํฉ๋๋ค.
์ํ state๋ idle, queued, running, completed, failed, canceled, interrupted์
๋๋ค. idle์ ํด๋น ์ ์ฅ ์คํ์ ์์ฒญํ ๋ถ์์ด ์๋ค๋ ๋ป์
๋๋ค. ์คํจยท์ทจ์ยท์ค๋จ ์์
์ ๋ค์ ์ ์ํ ์ ์์ต๋๋ค. ์ฌ์์ ํ ๋ณต๊ตฌํ ๋ฏธ์๋ฃ ๊ธฐ๋ก์ interrupted์ด๋ฉฐ ์ ์ ์ข
๋ฃ ๊ณผ์ ์์ ์ด๋ฏธ canceled๋ฅผ ์ ์ฅํ์ ์๋ ์์ต๋๋ค. ๋ณ๋ ์์
์ทจ์ endpoint๋ ์์ต๋๋ค. ์ญ์ ๊ฐ๋ฅํ ์ ์ฅ ๊ฒฐ๊ณผ๋ฅผ ์ง์ฐ๋ฉด ๋ถ์ ์์
๋ ์ทจ์ํ๊ณ ๋ถ์ ํ์ผ์ ์ ๊ฑฐํฉ๋๋ค.
| ์ํ ํ๋ | ์๋ฏธ |
|---|---|
id, runId
|
๋ถ์ ์๋ ID์ ์๋ณธ ์คํ ID. ์ฌ์๋ยท๊ฐฑ์ ์ผ๋ก ์ ์๋๊ฐ ์๊ธธ ์ ์์ |
version, analysisVersion
|
์ํยท์๋ต ํ์ ๋ฒ์ 1, ํ์ฌ ์์
์ ๊ณ์ฐ ๋ฒ์ 8. ์งํ์ definition, ๋ก๊ทธ์ rpcMetadataVersion๊ณผ ๋ณ๊ฐ |
phase, processedBytes, totalBytes, progress
|
ํ์ฌ ๋จ๊ณ์ ๋ก๊ทธ ์ฝ๊ธฐ ๋ฐ์ดํธ ์งํ๋ฅ (0โ100). ์ฝ๊ธฐ 100% ๋ค์๋ ๊ทธ๋ํยท์ ํ ๊ณ์ฐ๊ณผ ์ ์ฅ์ด ๋จ์ผ๋ฏ๋ก state: completed๋ฅผ ํ์ธ |
createdAt, startedAt, updatedAt, finishedAt
|
์์ ์๊ฐ. ์์ง ๋๋ฌํ์ง ์์ ๋จ๊ณ์ ์๊ฐ์๋ ์๋ฏธ๊ฐ ์์ |
sourceHash, sourceRevision, reused
|
์๋ณธ ํ๋ณธ์ ํด์, ๊ฐ๋ฒผ์ด ๋ณ๊ฒฝ ๊ฐ์ง์ฉ ๊ฐ, ํด์ ํ์ธ ํ ๊ธฐ์กด ๋ถ์ ์ฌ์ฌ์ฉ ์ฌ๋ถ |
savedAnalysisId |
๊ฒ์ฆยท์ฌ๋ถ์ ๋์ ๋ณด์กดํ๋ ์ด์ ์๋ฃ ๋ถ์ ID์ ๋๋ค. ๊ต์ฒด ์์ ์ค๋จยท์ฌ์์ ํ์๋ ์ ์งํฉ๋๋ค. |
artifactSlot |
์์
๋ฉํ๋ฐ์ดํฐ๊ฐ ์ ํํ ์ ์ฅ ์ฌ๋กฏ 0 ๋๋ 1์
๋๋ค. ์๋ตํ๋ฉด 0์ด๋ฉฐ ๋ถ์ endpoint๊ฐ ํด๋น ํ์ผ์ ์๋ ์ ํํฉ๋๋ค. |
snapshotAt |
POST ์ ์ ์์ ์ด ์๋๋ผ worker๊ฐ ๋ถ์ ์ฌ๋กฏ์ ์ป์ ๋ค ์ก์ ์๋ณธ ๊ฒฝ๊ณ |
error, resultUrl
|
์คํจ ๋ด์ฉ ๋๋ ์๋ ID๊ฐ ํฌํจ๋ ์๋ฃ ์ ์ฒด ๋ถ์ URL |
๋จ์ผยทํตํฉ ๋ถ์์ phase: saving ๋์์๋ running ์ํ์ด๋ฉฐ, ๊ฒฐ๊ณผ ํ์ผ์ ์ ์ฅํ๋ ์ค์ ์ํ ์กฐํยท์คํ ์ด๋ฒคํธ ์์ ยท์ค๋จ ์์ฒญ ์ฒ๋ฆฌ๋ฅผ ๊ณ์ํ ์ ์์ต๋๋ค. ์๋ฃ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ํ๊ธฐ ์ ์ ํ์ฌ ๋ถ์ ์๋์ธ์ง์ ์ทจ์ ์ฌ๋ถ๋ฅผ ๋ค์ ํ์ธํ๊ณ , ๊ฐ๋ณ ๋ถ์์ ์๋ณธ ์ญ์ ์ฌ๋ถ๋ ํ์ธํฉ๋๋ค.
์๋ฒ๋ ์๋ณธ์ด ๊ฐ์๋ ์๋ฃ ๋ถ์์ ๊ณ์ฐ ๋ฒ์ ์ด ํ์ฌ ๋ถ์๊ธฐ์ ๋ค๋ฅด๋ฉด stale: true๋ก ํ์ํฉ๋๋ค. ๊ฐ๋ณยท๋ฐฐ์น ์ํ์ Saved results ๋ชฉ๋ก ๋ชจ๋์ ์ ์ฉํฉ๋๋ค. ํด๋ผ์ด์ธํธ๋ ๋ถ์๊ธฐ ๋ฒ์ ๊ธฐ์ค์ ๋ฐ๋ก ๊ด๋ฆฌํ์ง ์๊ณ ์ด ํ์๋ก ๊ฐฑ์ ์ ์์ฒญํฉ๋๋ค. ๊ธฐ์กด ์๋ฃ ๋ถ์์ ๊ต์ฒด ์ ๊น์ง ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
๊ธฐ์กด ๋๊ธฐยท์คํ ์์
์ ?refresh=1์ด์ด๋ ์ฌ์ฌ์ฉํฉ๋๋ค. ์๋ฃ ์์
์ sourceRevision์ ๊ฐ๋ฒผ์ด ๋ณ๊ฒฝ ๊ฐ์ง์ฉ์ด๋ฉฐ ๋ชฉ๋กยท์ํ ์กฐํ์์ NAS ๋ก๊ทธ ๋ณธ๋ฌธ์ ์ฝ์ง ์์ต๋๋ค. Controller์ ์์นด์ด๋ธ ์ด๋์ ์๋ณธ ๋ด์ฉ์ด ๊ฐ์ผ๋ฉด ๋ก์ปฌ ๋ก๊ทธ ๋ถ๋ฆฌ ์ค์๋ revision์ ๋ณด์กดํฉ๋๋ค. ์์ธํ ๊ณ์ฝ์ ์๋ณธ ๋ณ๊ฒฝ์ ์ฐธ๊ณ ํ์ญ์์ค. revision ๋ณ๊ฒฝ ์ ๊ฐ๋ณ GET์ completed, stale: true๋ฅผ ๋ฐํํฉ๋๋ค. ์ผ๋ฐ POST๋ ์ ํ๋ ์์
์ฌ๋กฏ์์ ๋
ผ๋ฆฌ์ ์๋ณธ ๋ฐ์ดํธ์ ํ๋ณธ์ผ๋ก ๋ง๋ SHA-256์ธ sourceHash๋ฅผ ํ์ธํฉ๋๋ค. ํด์์ analysisVersion์ด ๊ฐ์ผ๋ฉด ๊ธฐ์กด ์๋ฃ ์์
IDยท๋ถ์ ํ์ผยท์ค๋
์ท ์๊ฐ์ ๋ณต์ํ๊ณ revision์ ๊ฐฑ์ ํ๋ฉฐ reused: true๋ฅผ ํ์ํฉ๋๋ค. ๋ฐ๋ผ์ ํ์ธ ์์
์ ํด๋งํ๋ค ์๋ฃ๋๋ฉด ์๋ ๋ถ์์ ID๋ก ๋์์ฌ ์ ์์ต๋๋ค. ํด์๊ฐ ๋ค๋ฅด๊ฑฐ๋ ๋ถ์๊ธฐ ๋ฒ์ ์ด ์ค๋๋์๊ฑฐ๋ ์ฝํ
์ธ ํด์๊ฐ ์๋ ์ด์ ๋ถ์์ด๋ฉด ๋ค์ ๊ณ์ฐํฉ๋๋ค. Images๊ฐ ์ด ๊ฒ์ฌ๋ฅผ ์๋ ์ํํ๋ฉฐ GET๋ง์ผ๋ก ์์
์ ์์ํ์ง ์์ต๋๋ค. Reanalyze๋ ?refresh=1๋ก ์๋ฃ ๋ถ์์ ํด์ ์ฌ์ฌ์ฉ์ ๊ฑด๋๋๋๋ค. ์ ๋ถ์์ผ๋ก ๊ณผ๊ฑฐ์ ์๋ ๊ธฐ๋ก์ ๋ณต์ํ ์๋ ์์ต๋๋ค.
ํ๋ณธ ํด์ ํ์์ sampled-sha256-v1:<hex>์
๋๋ค. ๋
ผ๋ฆฌ์ ์๋ณธ(scenario.yaml, experiment.json, events.jsonl, observations.jsonl)๋ง๋ค ์ด๋ฆยท์ ์ฒด ๋ฐ์ดํธ ๊ธธ์ดยทํ๋ณธ ์์นยทํ๋ณธ ๋ฐ์ดํธ๋ฅผ ๋ฐ์ํฉ๋๋ค. 64 KiB ์ดํ๋ ์ ์ฒด๋ฅผ ์ฝ๊ณ , ๋ ํฐ ํ์ผ์ ์ยท๋ค๋ฅผ ํฌํจํ 512๋ฐ์ดํธ ๊ตฌ๊ฐ 128๊ฐ๋ฅผ ์ฝ์ต๋๋ค. ๋ด๋ถ ์์น๋ ์๊ณ ๋ฆฌ์ฆ ๋ฒ์ ยท์ด๋ฆยท๊ธธ์ด๋ก ์ฌํ ๊ฐ๋ฅํ ์์ฌ ๋์๋ก ์ ํ๋ฏ๋ก ๋ค๋ฅธ ์ค๋
์ท์ด๋ ์์นด์ด๋ธ ์กฐ๊ฐ ๋ฐฐ์น์์๋ ๊ฐ์ ์์น๋ฅผ ๋น๊ตํฉ๋๋ค. ์๋ณธ๋ณ ์ต๋ 64 KiB๋ฅผ ์์ ์ ๊ทผ์ผ๋ก ์ฝ์ผ๋ฉฐ ๊ฒ์ฆ์ ๋ฐ์ดํธ ์งํ๋ฅ ์ ์ด ์ฝ๊ธฐ ์์ ๋ํ๋
๋๋ค. ๊ฐ์ ํฌ๊ธฐ์ ๋ณ๊ฒฝ์ด ํ๋ณธ ๋ฐ์ ์์ผ๋ฉด ํด์๊ฐ ๊ฐ์ ๋ณ๊ฒฝ์ ๋์น ์ ์์ต๋๋ค. ์ ์ฒด ํ์ผ ๋ฌด๊ฒฐ์ฑ ๊ฒ์ฆ์ด ์๋ ๊ทผ์ฌ์ ์ธ ์บ์ ํ์ธ์
๋๋ค. ๋ถ์ ๊ณ์ฐ ์์ฒด๋ ํ์ํ ์
๋ ฅ ์ ์ฒด๋ฅผ ์ฝ๊ณ ?refresh=1์ ๊ทธ ๊ณ์ฐ์ ๊ฐ์ ํฉ๋๋ค. ๊ธฐ์กด ์ ์ฒด ํด์ ๊ธฐ๋ฐ ๋ถ์์ ์๋ณธ revision์ด ๊ฐ์ผ๋ฉด ์บ์๋ฅผ ์ ์งํ๋ฉฐ, revision์ด ๋ฐ๋๋ฉด ํ๋ณธ ๊ธฐ์ค์ ๋ง๋ค๊ธฐ ์ํด ํ ๋ฒ ๊ณ์ฐํฉ๋๋ค. ๋ณด๊ด ๋ณต์ฌ์ ๋ฌด๊ฒฐ์ฑ ๊ฒ์ฆ๊ณผ ๋ณด์ยท๋น๋ ํด์๋ ์ ์ฒด ๋ด์ฉ์ ๊ณ์ ์ฌ์ฉํฉ๋๋ค.
๊ฐ๋ณ ์คํ๊ณผ ๋ฐฐ์น ํ๊ท ๋ชจ๋ ์๋ณธ ํด์๋ฅผ ๋น๊ตํ๊ฑฐ๋ ์ ๋ถ์์ ๊ณ์ฐํ๋ ๋์ ์ ์ฅ๋ ๋ถ์์ ๋จผ์ ํ์ํฉ๋๋ค. ์ด์ ์ค๋ ์ท ์๊ฐ์ ์ ์งํ๋ฉฐ ๊ฒ์ฆ ์งํ ์ํฉ์ ๋ณ๋๋ก ํ์ํฉ๋๋ค. ํด์๊ฐ ๊ฐ์ผ๋ฉด ๊ทธ๋ํยท๊ฒ์ ์ํ๋ฅผ ๊ทธ๋๋ก ์ ์งํ๊ณ ์ ๋ถ์์ด ์๋ฃ๋๋ฉด ๊ต์ฒดํฉ๋๋ค. ๊ฒ์ฆ ์คํจ ์์๋ ๊ธฐ์กด ๊ฒฐ๊ณผ์ ์ค๋ฅ ์๋ด๋ฅผ ํจ๊ป ๋จ๊น๋๋ค. ์๋ ์ฌ๋ถ์๋ ๋๊ธฐ ์ค ํ์ฌ ํ๋ฉด์ ์ ์งํฉ๋๋ค.
๊ต์ฒด ์์
์ด ์งํ ์ค์ด๊ฑฐ๋ ์คํจํ ์ํ์์ ์ด์ ๋ถ์์ ์ฝ์ ์ ์์ผ๋ฉด savedAnalysisId๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ธฐ์กด /result ๋๋ ๊ฐ๋ณ /summary ๊ฒฝ๋ก์ ํด๋น jobId์ &saved=1์ ๋ช
์ํ๋ฉด ์ด์ ๊ฒฐ๊ณผ๋ฅผ ์กฐํํ ์ ์์ต๋๋ค. ์ผ๋ฐ ์์ฒญ์ ๋ฏธ์๋ฃ ์์
์ ์ฌ์ ํ 409๋ฅผ ๋ฐํํฉ๋๋ค. ์ด์ ๊ฒฐ๊ณผ ์ฐธ์กฐ๋ Controller ์ฌ์์๊ณผ ํ์ผ ๊ฒ์ ์คํจ์๋ ๋ณด์กดํ๋ฉฐ ์๋ฃ๋ ๊ต์ฒด ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ ๋ ํด์ ํฉ๋๋ค. ๋ชจ๋ ๋ถ์ ๋ฒ์ ์ ์๊ตฌ ๋ณด๊ดํ๋ ๊ธฐ๋ฅ์ ์๋๋ฉฐ ๋ถ์ผ์นยท๊ต์ฒด๋ ID๋ 409์
๋๋ค. ํ๋ฉด์ ๋ค์ด๋ก๋ ๋งํฌ๋ ํ์ ์ค์ธ ๋ถ์ ID๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์๋ฃ ํ GET ๋๋ HEAD /api/v1/analysis-jobs/{id}/result?jobId={jobId}๋ ์ ์ฒด JSON, /summary?jobId={jobId}๋ ๋น๊ต์ฉ ์๋ฃ๋ฅผ ๋ฐํํฉ๋๋ค. jobId๋ฅผ ์ง์ ํ๋ฉด ๋ค๋ฅธ ๋ถ์ ์๋๋ฅผ ๋ด๋ ค๋ฐ์ง ์๋๋ก ํ์ธํ๋ฉฐ ์๋ตํ๋ฉด ํ์ฌ ์๋ฃ ์๋๋ฅผ ์ ํํฉ๋๋ค. ๋ฏธ์๋ฃยท์๋ ๋ถ์ผ์น๋ 409, ์คํ ๋ถ์ฌ๋ 404, ์๋ชป๋๊ฑฐ๋ ์ฝ์ ์ ์๋ ์ ์ฅ ์๋ฃ๋ ๋ณดํต 422์
๋๋ค. ๊ฒฝ๋ ์๋ต์ observations, scoreTimeline, timeline, bandwidthTimeline, research.messages๋ฅผ ๋น ๋ฐฐ์ด๋ก ๋๊ณ messageCountยท์งํยท์ง๊ณยท๋ถํฌยท์ ํฉ ๊ฒฐ๊ณผ๋ฅผ ์ ์งํฉ๋๋ค. ๊ฐ๋ณ ๋ฉ์์ง ๊ฒฝ๋ก๋ ์๋ณธ ์๊ณ์ด ์ฉ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ ์๋ต ๋ชจ๋ analysisId, analysisVersion, ์๋ณธ ๊ฒฝ๊ณ asOf๋ฅผ ํฌํจํฉ๋๋ค.
scoreTimeline์ ์ผ๋ฐ ๊ด์ธก ์ถ์ฝ๊ณผ ๋ณ๋๋ก ์์ธ ์ ์ ๊ตฌ์ฑ์์๋ฅผ ๋ณด์กดํฉ๋๋ค. ๊ทธ๋ฃนยท์ธก์ ์ ํ๋, ํ๋์ ๊ฒฐ์ธก ๊ท์น์ ์ ์ ๊ตฌ์ฑ์์ ์๊ณ์ด์ ์ ์ํฉ๋๋ค. ๊ฐ๋ณ ์ ์ฒด ๋ถ์๊ณผ ๋ฐฐ์น ๋ถ์์ ๋ณด์กดํ๊ณ ๊ฐ๋ณ ๋น๊ต์ฉ ์์ฝ์์๋ ๋น ๋ฐฐ์ด๋ก ๋ฐํํฉ๋๋ค.
research.receiverGroups๋ ์์ ํผ์ด ๊ทธ๋ฃน(group; ๋น ๋ฌธ์์ด์ ์ ๋ณด ๋๋ฝยท์ถฉ๋), ์์ ๋์ ์, ๋ฉ์์ง ์, ์์ฝ ํต๊ณ, ๊ฒฝ๋ overview, ์ ํยท์ค๋ณตยทํยทeager/lazy ๊ณก์ ๊ณผ ๊ธฐ๋ณธ latencyCDF/latencyHistogram์ ์ ๊ณตํฉ๋๋ค. ์ง์ฐ ๋ถํฌ๋ ๊ธฐ๋ณธ ์งํ ์ ์๋ฅผ, ๋๋จธ์ง ๊ทธ๋ฃน ๊ณก์ ์ ์ฐ๊ตฌ ์งํ ์ ์๋ฅผ ์ ์งํฉ๋๋ค. ๊ทธ๋ฃน ์๋ฃ๋ ๋ฐฐ์น ๊ฒฝ๋ํ ํ์๋ ๋ณด์กด๋ฉ๋๋ค. ์ TraceEvent์๋ ์ ํ ํ๋ group์ด ํฌํจ๋๋ฉฐ, ๊ณผ๊ฑฐ ๋ถ์์ ํ๋ฉด์ฉ ๋ค์ด์ํ๋ง ์ ์ ์ ์ฒด ์ ์ฅ ๊ทธ๋ํ์์ ๊ทธ๋ฃน์ ๋ณต์ํฉ๋๋ค. ์์ ๊ทธ๋ฃน๋ณ ์ง๊ณ ๊ธฐ์ค์ ์ฐธ๊ณ ํ์ญ์์ค.
GET /api/v1/experiments/{id}/analysis๋ 2๋ถ ์์ฒญ ์ ํ์ ๋๊ธฐ ํธํ ๊ฒฝ๋ก์
๋๋ค. ๋ณด์กด๋๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ๋ง๋ค์ง ์๊ณ ์๋ต์ ๊ณ์ฐํฉ๋๋ค. ๊ธด ๋ถ์๊ณผ ๋์ค ๋ค์ด๋ก๋์๋ job API๋ฅผ ์ฌ์ฉํ์ญ์์ค. ์ฐ๊ตฌ ์ ์๋ ์งํ ๊ฐ์ด๋, ๋ณด์กด ํ์ผ์ ๋ชจ๋ํฐ๋ง, ๋ธ๋ผ์ฐ์ ์กฐ์์ ์๊ฐํ์์ ๊ด๋ฆฌํฉ๋๋ค.
POST /api/v1/batch-analysis-jobs/{batchId}๋ ์คํ ์ ์ถ์ ๊ธฐ๋ก๋ ๋์ผ ๋ฐฐ์น์ ์๋ฃ run์ ๋ถ์ํฉ๋๋ค. ๋ชจ๋ ๋ฐฐ์น ๊ตฌ์ฑ์์ ์คํยท์ ๋ฆฌ ์๋ฃ์ ์ต์ 2๊ฐ์ ์๋ฃ run์ด ํ์ํ๋ฉฐ, ์คํ ์ค์ด๋ฉด 409, ์ ํจ ์๋ฃ run ๋ถ์กฑยท๋ฉํ๋ฐ์ดํฐ ๋ถ์ผ์น๋ 422, ๋ฐฐ์น๊ฐ ์์ผ๋ฉด 404์
๋๋ค. ์ธ์ฆยท์ค๋ณต ์ ์ยท์ฌ์๋ยท์ฌ์์ ์ฒ๋ฆฌ๋ ๊ฐ๋ณ ๋ถ์๊ณผ ๊ฐ๊ณ , ๊ฐ๋ณยท๋ฐฐ์น ์์
์ด ํฉ์ณ์ ์ต๋ 32๊ฐ์ ๋๊ธฐยท์คํ ์์
์ ๊ณต์ ํฉ๋๋ค. ์ต๋ 100ํ ๋ฐ๋ณต์ ํ๋์ ๋ฐฐ์น ์์
์ผ๋ก ์์ฐจ ์ฒ๋ฆฌํฉ๋๋ค.
์ํ์ ๋ฐฐ์น ์๋ณ์๋ batchId์ด๋ฉฐ runId๋ ๋น์ด ์์ต๋๋ค. ์ ํํ runIds, completedRuns, totalRuns, expectedRuns, ๊ตฌ์ฑ์ ์๋ช
membership๋ ์ ๊ณตํฉ๋๋ค. ๊ณตํต ์์
์ฌ๋กฏ์์ run์ ํ๋์ฉ ์บก์ฒํด ์๋ณธ ํด์๋ฅผ ๋จผ์ ํ์ธํ๋ฉฐ, ๋ฐ์ดํธ ํ๋๋ ํ์ฌ ๋จ๊ณ์ run์ ๋ํ๋
๋๋ค. ๊ณ์ฐ ์งํ๋ฅ ์ run๋ณ ๋์ผ ๊ฐ์ค์น์
๋๋ค. snapshotAt์ ๊ฐ์ฅ ์ต๊ทผ์ ๋ถ์ํ run์ ๊ฒฝ๊ณ์ด๋ฉฐ runs[].asOf๋ ๊ฐ๋ณ ๊ฒฝ๊ณ์
๋๋ค. ๊ตฌ์ฑ์ยท์ํยท์๋ณธ revision ๋ณ๊ฒฝ ์ ์ด์ ์๋ฃ ์บ์๋ฅผ idle, stale: true๋ก ํ์ํฉ๋๋ค. ์ผ๋ฐ POST๋ ์๋ฃ run์ ํ๋ณธ ํด์, ๊ตฌ์ฑ์ ์๋ณ์ยท๊ฒฐ๊ณผ, ๊ณผ๊ฑฐ ์๋ ์ง๊ณ๋ฅผ ๋ฐ์ํ ๋ฐฐ์น sourceHash๋ฅผ ๋น๊ตํฉ๋๋ค. ๊ฐ์ผ๋ฉด ์๋ ๋ฐฐ์น ๋ถ์ ํ์ผ๊ณผ ID๋ฅผ ์ฌ์ฌ์ฉํ๊ณ ๋ค๋ฅด๋ฉด ๋ค์ ๊ณ์ฐํฉ๋๋ค. ์ ์ธ๋ ์ด๋ฒคํธ ๋ก๊ทธ์ ๋ฉ๋ชจ๋ ํต๊ณ ์
๋ ฅ์ด ์๋๋๋ค. ๋ก์ปฌ revision์ ์ ๊ณต๋๋ ํ์ผ ์๋ณ์ยท๋ณ๊ฒฝ ์๊ฐ๋ ๋ฐ์ํ๋ฏ๋ก ํฌ๊ธฐยทmtime์ ์ ์งํ ์ฌ์์ฑ๋ ํด์ ํ์ธ์ ์์ฒญํฉ๋๋ค. ์์นด์ด๋ธ revision์ NAS ๋ณธ๋ฌธ ๋์ manifest ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. NAS ๊ฐ์ฒด๋ ๋ถ๋ณ์ผ๋ก ์ทจ๊ธํ๋ฉฐ ์ ์ฅ ์ํฌํ๋ก๋ฅผ ํตํด ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค. ?refresh=1์ ๊ฐ์ ๋ก ๋ค์ ๊ณ์ฐํฉ๋๋ค. ํด์ ํ์ธยท๊ณ์ฐยท์ ์ฅ ์ค ๊ตฌ์ฑ์์ด๋ ์๋ณธ revision์ด ๋ฐ๋๋ฉด ์์
์ ์คํจ ์ฒ๋ฆฌํ๋ฏ๋ก ํ์ฌ ์๋ณธ์ผ๋ก ์ฌ์๋ํ์ญ์์ค.
๊ตฌ์ฑ์ ์๋ช ์๋ ํ์ฌ ์๋ฃ ๊ธฐ์ฌ Run์ ์๋ณธ revision๋ง ๋ฐ์ํฉ๋๋ค. ์ ์ธ๋ ์๋์ ์ด์ ์๋์ ์๋ณ์ยท๊ฒฐ๊ณผ๋ ๊ณ์ ๋ฐ์ํ์ง๋ง, ํต๊ณ์ ์ฌ์ฉํ์ง ์๋ ๋ก๊ทธ ๋ณ๊ฒฝ์ผ๋ก ๋ฐฐ์น ํ๊ท ์ ์๋ณธ ๊ฒ์ฆ์ ์์ฝํ์ง ์์ต๋๋ค.
ํตํฉ ๊ฒฐ๊ณผ์ reliability๋ attempts, failed, canceled, interrupted, retries, failedAttemptRate, unknownAttempts, unverifiedRuns, incompleteRuns, environments, environmentChanged, warnings๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ค์ ์์ํ ์๋์ ์ญ์ ํ ๋ณด์กด๋ ์๋ ์ด๋ ฅ์ ์ง๊ณํ๋ฉฐ ๋ฏธ์์ ๋๊ธฐ ๊ธฐ๋ก์ ์ ์ธํฉ๋๋ค. ์คํจ์จ์ failed / attempts์ด๊ณ ์งํ ํ๊ท ์ ๊ณ์ ์ต์ ์๋ฃ ํ์ฐจ๋ง ์ฌ์ฉํฉ๋๋ค. ํ๊ฒฝ๋ณ fingerprint, Run ID, Agent ์ค๋
์ท๊ณผ Controller ๋น๋ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ง๋ง ํธ์คํธ ๋ถํยท๋ฏธ๊ธฐ๋ก ๋คํธ์ํฌ ์ฐจ์ด๋ fingerprint ๋ฒ์ ๋ฐ์
๋๋ค.
๊ฒฐ๊ณผ๋ version: 1, analysisVersion: 8, aggregation: "equal-run-mean-v1", ๋ฐฐ์นยท์๋ ID, expectedRuns, missingRuns, excluded, runs, summary๋ฅผ ์ ๊ณตํฉ๋๋ค. summary๋ metrics.*, research.*, bandwidth.sentBytes, bandwidth.receivedBytes๋ณ average, deviation(run ๊ฐ ํ๋ณธ SD), median, count(์ ํจ run ์)์
๋๋ค. ๊ฒฐ์ธก ํ๊ท ์ null, ์ ํจ run 1๊ฐ์ SD๋ null์
๋๋ค. runs๋ ๊ทธ๋ํ ์งํยท๊ด์ธกยท๋์ญํญยท๋ถํฌ์ ๋ฉ์์ง ์๊ณ์ด/์์ ๊ณก์ /๊ธฐ์ ์๋ฅผ ๋ด์ research.overview๋ฅผ ๋ณด์กดํ๊ณ ์์ ๋ฉ์์งยท๋
ธ๋ ๊ฒฝ๋ก๋ฅผ ์๋ตํฉ๋๋ค. ํ๊ท ์ฐจํธ์ ์ถ ์ ๋ ฌยท๋ถํฌ ๊ท์น์ ํตํฉ ํ๊ท ์ฌ์ฉ๋ฒ์ ์ฐธ๊ณ ํ์ญ์์ค.
์๋ฃ ํ์ผ์ <data-dir>/batch-analyses/{batchId}/job.json, result.json์ ์ ์ฅ๋ฉ๋๋ค. ์ฐฝ ์ข
๋ฃ์ ์๋ฒ ์ฌ์์ ํ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ช
์์ ์ธ jobId ๋ค์ด๋ก๋๋ ํด๋น ์๋ฃ ์ค๋
์ท์ ๊ณ ์ ๋๋ฉฐ ๋ค๋ฅธ ์๋๋ก ๊ต์ฒด๋์ผ๋ฉด 409์
๋๋ค. ๊ฐ๋ณ ์๋ณธ ์ญ์ ๋ ๊ธฐ์กด ํตํฉ ์ค๋
์ท ํ์ผ์ ์ง์ฐ์ง ์์ต๋๋ค. ๋ณ๊ฒฝ๋ ๊ตฌ์ฑ์ผ๋ก ๋ค์ ๋ถ์ํ๋ฉด ํ์ฌ ํ์ผ์ ๊ต์ฒดํ๋ฏ๋ก ์ด์ ๊ฒฐ๊ณผ๊ฐ ํ์ํ๋ฉด ๋จผ์ ๋ค์ด๋ก๋ํ์ญ์์ค.
์ ๊ณต๋๋ Swarm stack์ Controller์ --network-manager(KPL_NETWORK_MANAGER_URL)์ Agent์ --auto-reset-network --control-network NAME์ผ๋ก ์ด ๊ฒฝ๋ก๋ฅผ ํ์ฑํํฉ๋๋ค. ์ด ์ต์
์ ์๋ตํ ์ฌ์ฉ์ ์ง์ ๋ฐฐํฌ๋ ์ด์ ๋คํธ์ํฌ ์๋ช
์ฃผ๊ธฐ๋ฅผ ์ ์งํฉ๋๋ค. Stack์ ์ ์ด ์๋น์ค๋ฅผ ๊ณ ์ overlay์ ๋ฐฐ์นํ๊ณ control manager์ Docker socket๊ณผ ์์ ๋ณต๊ตฌ volume์ ์ฌ์ฉํ๋ network-manager๋ฅผ ์คํํฉ๋๋ค. Standalone gateway์๋ Docker socket์ด๋ ํธ์คํธ ๊ฒฝ๋ก๋ฅผ ๋ง์ดํธํ์ง ์์ต๋๋ค. ๋ฐฐํฌยท์
๊ทธ๋ ์ด๋ ์๊ตฌ์ฌํญ์ ์ฐธ๊ณ ํ์ญ์์ค.
Controller๋ ๋งค Run ์ ์ ๋นํ์ฑ Agent๋ฅผ ํฌํจํ ๋ฑ๋ก Agent ๋ชจ๋์ POST /api/v1/network/fence๋ฅผ ๋ณด๋
๋๋ค. ๋ณธ๋ฌธ์ {runId, epoch, requestedAt}์
๋๋ค. Agent๋ ๊ธฐ์กด ํ๋ก์ธ์ค ์ ๊ฑฐ๊ฐ ํ์ธ๋ ๊ฒฝ์ฐ์๋ง ์ ์
์ฅ์ ๋ง๊ณ Docker์ ๊ด๋ฆฌ ๋์ Peer ์ปจํ
์ด๋๊ฐ ๋จ์๋์ง๋ ๊ฒ์ฌํฉ๋๋ค. ๊ฑฐ์ ํ๊ฑฐ๋ ์ฐ๊ฒฐ๋์ง ์๋ Agent๊ฐ ์์ผ๋ฉด ์ค๋น๊ฐ ์ค๋จ๋ฉ๋๋ค. ์ดํ ๊ฐ์ ์๋ณ ์ ๋ณด์ Agent IDโ์ ์ด URL์ agents ๋งต์ Manager์ POST /api/v1/network/prepare๋ก ๋ณด๋
๋๋ค. Manager๋ ์ค๋น๋ฅผ ์ง๋ ฌํํ๊ณ ์ค๋๋ ์์ฒญ์ ๊ฑฐ์ ํ๋ฉฐ Swarm ๋
ธ๋ Ready, ๋คํธ์ํฌ ์์ ๊ถยท๊ธฐ๋ณธ IPv4 ์ค์ ยท์๋น์ค ์ฐธ์กฐ๋ฅผ ํ์ธํฉ๋๋ค. Subnet๊ณผ gateway๋ฅผ ๋ณด์กดํ๋ฉด์ ์ network ID๋ก ์์ฑํ๋ฉฐ ๋คํธ์ํฌ ๊ฐ์ ์ญ์ ๋ ํ์ง ์์ต๋๋ค. ์ญ์ ํ ์์ฑ์ด๋ ์๋ต์ด ์คํจํด๋ ๋ก์ปฌ ๋ณต๊ตฌ ํ์ผ์ ๊ธฐ์กด ํ ๋น ์ค์ ์ ๋ณด์กดํฉ๋๋ค.
Docker ์ญ์ ์ฑ๊ณต ์๋ต ์ดํ Manager๋ ํตํฉ network ๋ชฉ๋ก์์ ์ ํํ Peer network ์ด๋ฆ์ด ์ฌ๋ผ์ง ๊ฒ์ ํ์ธํ ๋ค ๊ต์ฒด ๋คํธ์ํฌ๋ฅผ ์์ฑํฉ๋๋ค. ์ญ์ ๋ฐ์ ๋๊ธฐ, ๋ช
์์ ์ธ network with name ... already exists ๊ฑฐ์ ์ ์ฌ์๋, ์์ฑ ์ฑ๊ณต ํ ๋ชฉ๋ก ๋ฐ์ ๋๊ธฐ๋ ๊ธฐ์กด Manager ์์
์ ํ ์์์ ํฉ๊ณ 1๋ถ์ ๊ณต์ ํฉ๋๋ค. ํด๋ง์ ์ทจ์ํ ์ ์๊ณ ์กฐํ ์คํจ๋ฅผ ์ญ์ ํ์ธ์ผ๋ก ์ทจ๊ธํ์ง ์์ต๋๋ค. ์ญ์ ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ค ๋ค๋ฅธ ID๊ฐ ๋ํ๋๋ฉด ์ค๋น๋ฅผ ์ค๋จํ๋ฉฐ ํด๋น ๋คํธ์ํฌ๋ฅผ ์ญ์ ํ์ง ์์ต๋๋ค.
์์ฑ ์๋ต์ด ์คํจํ๋ฉด inspect๋ก ์ค์ ์ํ๋ฅผ ํ์ธํฉ๋๋ค. ์ ๋คํธ์ํฌ๊ฐ ํ์ฌ epochยท์์ ์์ ๊ถยทํ ๋น ์ค์ ๊ณผ ์ผ์นํ๊ณ endpoint ๋ฐ ์๋น์ค ์ฐธ์กฐ๊ฐ ์์ ๋๋ง ํ์ ์ค๋น๋ฅผ ๊ณ์ํ ์ ์์ต๋๋ค. ๊ทธ ์ธ์๋ ๋ช ์์ ์ธ ์ด๋ฆ ์ถฉ๋๋ง ์ํ๋ฅผ ๋ค์ ํ์ธํ ๋ค ์ฌ์๋ํ๋ฉฐ, ์ผ๋ฐ ์ค๋ฅ๋ ์์ฑ ์ฌ์๋๋ก ์ฒ๋ฆฌํ์ง ์์ต๋๋ค. ์๋ network ID๋ฅผ ์ ๋คํธ์ํฌ๋ก ์๋ฝํ์ง ์์ต๋๋ค. ๋ชฉ๋ก ๋ฐ์ ์ง์ฐ, ์ง์์ ์ธ ์ถฉ๋, ์ทจ์ ๋๋ ํ์ธ ๋ถ๊ฐ๋ฅํ ์ํ๊ฐ ํด์๋์ง ์์ผ๋ฉด ํ์ฑํํ์ง ์์ต๋๋ค. ์ด ๋๊ธฐ ์๊ฐ์๋ ์คํยท์๋๋ฆฌ์ค schedule ์๊ณ๊ฐ ์งํ๋์ง ์์ต๋๋ค.
์๋ต์ {runId, epoch, networkId, networkName, gatewayUrl, peerGatewayUrl}์
๋๋ค. Controller๋ ์ด๋ฅผ ๊ฐ Agent์ POST /api/v1/network/activate๋ก ๋ณด๋ด๊ณ ๋ชจ๋ ํ์ธ๋ ๋ค Run์ startedAt์ ๊ธฐ๋กํ๊ณ phase๋ฅผ ์์ํฉ๋๋ค. Experiment.peerNetworkId์ ์ ์๋ณ์๋ฅผ ๋ณด์กดํฉ๋๋ค. CreateNodeRequest.peerNetworkId๋ Agent๊ฐ ์ค๋นํ ํ์ฌ Runยท์๋์ ์
์ฅ ์กฐ๊ฑด๊ณผ ์ผ์นํด์ผ ํ๋ฉฐ Docker ์์ฑ์๋ ๊ณ ์ ID๋ฅผ ์ฌ์ฉํฉ๋๋ค. Worker๋ ์ฒซ ์ปจํ
์ด๋ ์ฐ๊ฒฐ ๋ overlay๋ฅผ ๊ตฌ์ฑํ ์ ์์ผ๋ฏ๋ก Agent๋ ์์ ํ ์ค์ ์ฐ๊ฒฐ์ network ID๋ ํ์ธํฉ๋๋ค. ๋ฆ์ ์์ฑ ์์ฒญ์ด ๊ฐ์ ์ด๋ฆ์ ๊ต์ฒด ๋คํธ์ํฌ์ ์
์ฅํ ์ ์์ต๋๋ค. ์ค๋น ์คํจ ์ phase๋ฅผ ์์ํ์ง ์๊ณ ๊ธฐ์กด ์คํจยท์ ๋ฆฌยท์์ฝ ์ฒ๋ฆฌ ๊ท์น์ ๋ฐ๋ฆ
๋๋ค.
์ค๋น endpoint์๋ ๋ด๋ถ Bearer ์ธ์ฆ์ด ํ์ํฉ๋๋ค. ๊ฐ endpoint๋ JSON ๊ฐ ํ๋๋ง ํ์ฉํ๊ณ ์ ์ ์๋ ํ๋๋ฅผ ๊ฑฐ๋ถํฉ๋๋ค. Agent ๋ณธ๋ฌธ์ 64 KiB, Manager ๋ณธ๋ฌธ์ 1 MiB ํ๋์
๋๋ค. Agent๋ ํ์ธ ์ 204, ์๋ชป๋ ์
๋ ฅ์ 400, ์ค๋นยท์ ๋ฆฌยทํ์ฑํ๋ฅผ ํ์ธํ ์ ์์ผ๋ฉด 409๋ฅผ ๋ฐํํฉ๋๋ค. Manager๋ ์ฑ๊ณตํ JSON ์๋ต์ 200, ์๋ชป๋ ๋ณธ๋ฌธ์ 400, ๊ฑฐ์ ยท์คํจํ ์ค๋น์ 409๋ฅผ ์ฌ์ฉํ๋ฉฐ ์ธ์ฆ ์คํจ๋ 401์
๋๋ค. ์ ์ฒด ์ค๋น ์ ํ์ 4๋ถ์ด๋ฉฐ Manager ์์
์ 3๋ถ, Agent ํธ์ถ์ 45์ด๋ก ์ ํํฉ๋๋ค. Gateway๋ ์ธ์ฆ๋ HTTP ์ ์ดยทtelemetry์ ๊ณต๊ฐ Controller ์๊ฐ health ์์ฒญ์ overlay ์ฌ์ด์์ ์ ๋ฌํ๋ฉฐ Peer์ P2P ํต์ ์ ์ง์ ์ฐ๊ฒฐ์ ์ ์งํฉ๋๋ค. Gateway ์์์ ์ ์ด ์๋น์ค ๋ชจ๋ํฐ๋ง์ ํฌํจํฉ๋๋ค. Gateway ๊ต์ฒด๋ ๋ค์ ์ ๋ฆฌ ํ์ธ ๋จ๊ณ๊น์ง ๋ฏธ๋ฃน๋๋ค. ์๋น์ค ์ค์งยทDocker ์ฌ์์ยท๋ฐ์ดํฐ volume ๋ณ๊ฒฝ์ ํ์ง ์์ต๋๋ค. ์ด์ ์ฐ๊ฒฐ์ฑ๊ณผ ๋๊ท๋ชจ ๋ฐ๋ณต ์คํ์ ๋ณ๋ ๋ฐฐํฌ ๊ฒ์ฆ์ด ํ์ํฉ๋๋ค.
์ด REST/JSON endpoint๋ ์ปดํฌ๋ํธ ์ฌ์ด ํต์ ์ ์ฌ์ฉํฉ๋๋ค. ๋ฑ๋ก, heartbeat์ ์ ๋ฌ event๋ Controller๋ก, lifecycle ๋ช ๋ น์ Agent๋ก ์ ์กํฉ๋๋ค.
| ํธ์ถ์ โ ์๋ฒ | Method | Path | ๋ชฉ์ |
|---|---|---|---|
| Agent โ Controller | POST |
/api/v1/agents/register |
Agent instance ๋ฑ๋ก |
| Agent โ Controller | POST |
/api/v1/agents/heartbeat |
Agent์ Peer snapshot ๋ณด๊ณ |
| Agent โ Controller | POST |
/api/v1/events/batch |
batch๋น ์ต๋ 5000๊ฐ event ์ ๋ฌ |
| Controller โ Agent | GET |
/api/v1/status |
Agent์ Peer ์ํ ๊ฐฑ์ |
| Controller โ Agent | POST |
/api/v1/registration/refresh |
์ค์ ๋ Controller์ ์ธ์ฆ๋ ์ฌ๋ฑ๋ก ํ AgentยทPeer ์ํ ๋ฐํ; Peer ์ฌ์์ ์์ |
| Controller โ Agent | POST |
/api/v1/nodes |
CreateNodeRequest๋ก Peer ์์ฑ |
| Controller โ Agent | DELETE |
/api/v1/nodes |
๊ธฐ์กด run์ fence ์ฒ๋ฆฌํ๊ณ ๋จ์ Peer์ ๋๊ธฐ telemetry๋ฅผ ๋ชจ๋ ์ ๋ฆฌํ ๋ค 204 ๋ฐํ. Controller ์ข
๋ฃ ์ ์ฌ์ฉ |
| Controller โ Agent | DELETE |
/api/v1/nodes/{nodeId} |
Peer ํ๋์ ์ข ๋ฃ ์์ฒญ |
| Controller โ Agent | POST |
/api/v1/nodes/{nodeId}/publish |
publish ์์ฒญ ์ค๊ณ |
| Controller โ Agent | POST |
/api/v1/nodes/{nodeId}/mesh-freeze |
ready Peer์์ ํ์ฉํ GossipSub ๋ฉ์ ๋๊ฒฐ์ ์ ์ฉํ๊ณ ์๋ต ๋ฐํ |
| Peer โ Agent | POST |
/api/v1/nodes/{nodeId}/status |
ํด๋น Peer์ ์ต์ ์ํ ๋ณด๊ณ |
| Peer โ Agent | POST |
/api/v1/telemetry |
telemetry batch ์ ์ถ |
| Agent โ Peer |
GET / POST
|
/health / /publish
|
Peer HTTP API๋ก readiness ํ์ธ ๋๋ publish |
| Agent โ Peer | POST |
/mesh-freeze |
ํด๋น nodeยทRunยทgeneration์ ๋ฉ์ ๋๊ฒฐ ์ ์ฉ |
CreateNodeRequest.experimentStartedAt์ ํ์ฌ ์คํ์ startedAt์ ๋ณต์ฌํ RFC3339 ์๊ฐ์ด๋ฉฐ Peer ํ๋ก์ธ์ค ์ค์ ์๋ ์ ์ฅํฉ๋๋ค. config.network.schedule์ ๋ณ๊ฒฝ ๋ชฉ๋ก์ด ์๊ณ reference: experiment-start์ด๋ฉด ํ์์ด๋ฉฐ, ๋๋ฝ ์ Peer๋ฅผ ์์ฑํ๊ธฐ ์ ์ ๊ฑฐ๋ถํฉ๋๋ค. Controller๊ฐ ์๋์ผ๋ก ์ฑ์ฐ๋ ๋ด๋ถ ์์ฒญ ํ๋๋ก ์๋๋ฆฌ์ค YAML์๋ ๋ฃ์ง ์์ต๋๋ค. ์ ์ network ์ค์ ๊ณผ Peer ๊ธฐ์ค ์์ฝ์๋ ํ์ํ์ง ์์ต๋๋ค.
createReplay: true๋ฅผ ์๋ฆฌ๋ Agent๋ POST /api/v1/nodes ์๋ต์ด ๋๊ธด ๊ฒฝ์ฐ์ ๋ณต๊ตฌ๋ฅผ ์ง์ํฉ๋๋ค. Controller๋ ํด๋น Agent์ startedAt์ CreateNodeRequest.agentStartedAt์ ๋ณต์ฌํ๋ฉฐ, Agent ์คํ ์ธ์คํด์ค๊ฐ ๋ค๋ฅด๋ฉด ์
์ฅ ์ ์ 409๋ก ๊ฑฐ์ ํฉ๋๋ค. ๊ฐ์ ๋
ธ๋ ID์ ๋์ผํ๊ฒ ๋์ฝ๋ฉ๋ ์์ฒญ์ด๋ฉด ๋์ ์์ฒญ์ ์ต์ด ์
์ฅ ์ฒ๋ฆฌ๊ฐ ๋๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ , ์ดํ ์์ฒญ์ ๋ก์ปฌ ์ด๋ ฅ์ ์ข
๋ฃ ์ํ๋ฅผ ํฌํจํ ๊ธฐ์กด Peer ์ํ๋ฅผ ๋ฐํํฉ๋๋ค. ์์ฒญ ๋ด์ฉ์ด ๋ค๋ฅด๊ฑฐ๋ ์ต์ด ์
์ฅ ์ฒ๋ฆฌ๊ฐ ์คํจํ๋ค๋ฉด 409์
๋๋ค. Agent๋ ๊ธฐ์กด ํ๋ก์ธ์คยท์ด๋ ฅ ๊ธฐ๋ก์ metadata.createRequestHash์ metadata.createAdmission์ SHA-256 ์์ฒญ ์ง๋ฌธ๊ณผ ์
์ฅ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ดํ๋ฉฐ ๋ณ๋๋ก ๊ณ์ ์ปค์ง๋ ์์ฒญ ์บ์๋ฅผ ๋ง๋ค์ง ์์ต๋๋ค. ๋ ํ๋๋ Agent๊ฐ ๊ด๋ฆฌํฉ๋๋ค. ๋ณต๊ตฌ๋ก Peer๋ฅผ ๋ค์ ์คํํ๊ฑฐ๋ lifetime์ ์ด๊ธฐํํ์ง ์์ต๋๋ค. agentStartedAt์ ์๋ตํ ์์ฒญ์ ๊ธฐ์กด์ฒ๋ผ ์ค๋ณต ID๋ฅผ ๊ฑฐ์ ํฉ๋๋ค.
์ง์ Agent์์๋ EOFยท์๋ต ์๋ฆผยท์ฐ๊ฒฐ reset/refusalยทbroken pipeยท์์ฒญ timeout์ ํํด ๊ฐ์ Agent URLยท์คํ ์ธ์คํด์ค๋ก ์ด 3ํ๊น์ง ์๋ํ๋ฉฐ, ์ฌ์ด ๋๊ธฐ๋ 250ms์ 500ms์ ๋๋ค. ๊ฐ ์์ฒญ์ ๊ธฐ์กด HTTP ์ ํ์ 10์ด์ด๊ณ ์๋๋ฆฌ์ค context๊ฐ ๋ ์งง์ผ๋ฉด ์ด๋ฅผ ๋ฐ๋ฆ ๋๋ค. ๋ณต๊ตฌ ์ค ์ต์ข ํ๋กํยทseedยทlifetimeยท๋ ธ๋ ID๋ ๊ณ ์ ํ๋ฉฐ ์คํ ์๊ณ๋ ๊ณ์ ์งํํฉ๋๋ค. HTTP ๊ฑฐ์ ๊ณผ ์๋ชป๋ ํ์ธ ์๋ต์ ํต์ ์ฌ์๋ ๋์์ด ์๋๋๋ค. ๊ตฌ๋ฒ์ Agent์๋ ์ ํ๋๋ฅผ ๋ณด๋ด๊ฑฐ๋ ์์ฑ ์์ฒญ์ ์๋ ์ฌ์ ์กํ์ง ์์ต๋๋ค. ์ ์กํ ์์ฒญ์ ์์ฑ ์ฌ๋ถ๋ฅผ ๋๋ด ํ์ธํ์ง ๋ชปํ๋ฉด Agent๊ฐ ํด๋น Peer๋ฅผ ๋ณด๊ณ ํ๊ฑฐ๋ ํด๋น ์คํ ์ธ๋์ ์ฐจ๋จยท์ ๊ฑฐ ์๋ฃ๋ฅผ ํ์ธํ ๋๊น์ง ์์ฝ ์ฉ๋์ ์ ์งํฉ๋๋ค. ๋ถํ์คํ ์์ฒญ์ ๋ค๋ฅธ Agent์ ์ฌ๋ฐฐ์นํ์ง ์์ผ๋ฉฐ, ๋น inventory๋ง์ผ๋ก ๋ฆ์ ์์ฑ ์์ฒญ์ด ๋์ฐฉํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ํ๋จํ์ง ์์ต๋๋ค.
์์ฝ Peer์ node metadata.networkRequested๋ ์์ฒญํ network ์ค์ ์ ์ ์งํ๊ณ , metadata.networkSchedule์ seed๋ก ํ์ ํ ๊ตฌ์ฒด์ delay๋ฅผ ํฌํจํ Agent์ ์์ฝ ๊ณํ์ ๋ด์ต๋๋ค. ์ด ๋ฉํ๋ฐ์ดํฐ ๊ฐ์ JSON ๋ฌธ์์ด์
๋๋ค. metadata.network๋ ํ์ฌ ๊ตฌ์ฒด์ ์ธ ์กฐ๊ฑด์ ๋ํ๋ด๋ฉฐ networkPending์ด "true"์ธ ๋์์ ์์ง ์ ์ฉ ํ์ธ ์ ์
๋๋ค. Peer์์ ์ ์ฉ์ด ์ฑ๊ณตํ๋ฉด ์ํ ๋ณด๊ณ ์ networkPending: "false", networkRevision(10์ง์ ๋ฌธ์์ด, ์ด๊ธฐ ์ํ๋ 0, ์ดํ ๋ณ๊ฒฝ ๋ชฉ๋ก์ 1๋ถํฐ ์์ํ๋ ๋ฒํธ), networkAppliedAt(RFC3339)์ ์ค์ ํฉ๋๋ค. ๋ฆ์ ์
์ฅ์ด๋ ํ์ด๋จธ ์ง์ฐ ์ ์ค๊ฐ revision์ ๊ฑด๋๋ธ ์ ์์ต๋๋ค. Agent๋ ์ด์ revision์ผ๋ก์ ์ญ์ ์ ๋ง๊ณ heartbeat๋ก ์ ์ฉ ์ํ๋ฅผ Controller์ ์ ๋ฌํฉ๋๋ค. ์ด ํ๋๋ ๋ณด๊ณ ์ํ์ด๋ฉฐ ์คํ ์ค์ธ Peer์ ์กฐ๊ฑด์ ๋ฐ๊พธ๋ API๊ฐ ์๋๋๋ค.
์ฃผ๊ธฐ์ ์ธ Agent heartbeat๋ partial: true๋ฅผ ์ฌ์ฉํ๊ณ JSON ๋ณธ๋ฌธ์ ์ต๋ 10MiB๋ก ๋๋๋๋ค. ๊ฐ๋ณ Peer ๊ธฐ๋ก์ด ํ๋๋ฅผ ๋์ผ๋ฉด ๋
ธ๋ ์ด๋ฆ์ ํฌํจํ ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๊ณ ๋ฏธํ์ธ ์ํ๋ก ์ ์งํฉ๋๋ค. ์คํ ์ค Peer, ์ปจํ
์ด๋ ์ ๊ฑฐ์ ์คํจํ Peer, Controller ํ์ธ์ ๊ธฐ๋ค๋ฆฌ๋ ์ข
๋ฃ Peer๋ ๋ฉ๋ชจ๋ฆฌ์ ๋จ์ต๋๋ค. ์ ๊ฑฐ๊ฐ ํ์ธ๋ ๊ธฐ๋ก์๋ metadata.cleanupComplete="true"๊ฐ ๋ถ์ผ๋ฉฐ, ํ๋ก์ธ์ค๊ฐ ์คํจํ๋๋ผ๋ ์ปจํ
์ด๋ ์ ๊ฑฐ๊ฐ ์ฑ๊ณตํ๋ฉด ํด๋น๋ฉ๋๋ค. ์ต์ข
์ํยท์ค๋ฅ๋ ๋ณด์กดํ๋ฉด์ ๊ณผ๊ฑฐ ํ ํด๋ก์ง์ ์ ์ ๋ฐ์ดํฐ๋ ํด์ ํฉ๋๋ค.
Controller ํ์ธ ์ดํ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์
์ ์ต๊ทผ ์ข
๋ฃ ๊ธฐ๋ก 64๊ฐ๋ง ๋จ๊ธฐ๊ณ ์ค๋๋ ์ถ์ฝ ๊ธฐ๋ก์ ๋ก์ปฌ bbolt ํ์ผ ํ๋์ธ <agent-data-dir>/peer-history/nodes์ ์ ํ๋ ํธ๋์ญ์
์ผ๋ก ์ ์ฅํ ํ ๋ฉ๋ชจ๋ฆฌ์์ ์ ๊ฑฐํฉ๋๋ค. ์ฃผ๊ธฐ heartbeat๋ ํ์ธ๋ ์ข
๋ฃ ๊ธฐ๋ก์ ์๋ตํฉ๋๋ค. GET /api/v1/status์ GET /api/v1/nodes๋ ํ์ฌ inventory์ ์ต๊ทผ/๋ฏธํ์ธ ๊ธฐ๋ก์ ๋ฐํํ๋ฉฐ ๊ณผ๊ฑฐ ๋ชจ๋ Peer๋ฅผ ๋ฐํํ์ง ์์ต๋๋ค. full status๋ ๋๋ฝ๋ ํ์ฑ ๋
ธ๋๋ฅผ ๊ณ์ ์ ๋ฆฌํ์ง๋ง ์ ๊ฑฐ๊ฐ ํ์ธ๋ ์คํจ ๊ธฐ๋ก์ ์ฑ๊ณต ์ํ๋ก ๋ฐ๊พธ์ง ์์ต๋๋ค. ๊ณผ๊ฑฐ ๊ธฐ๋ก์ Controller ๊ฒฐ๊ณผ์ Agent ๋ก์ปฌ ์ด๋ ฅ์ ๋จ์ต๋๋ค.
์ฌ๋ฑ๋กํ๋ฉด ๋ฉ๋ชจ๋ฆฌ์ ์ต๊ทผ ๊ธฐ๋ก์ ๋ค์ ์ ๋ฌํ๊ณ , ๋งค ํ์ฑ heartbeat ๋ค์ ๋์คํฌ ์ด๋ ฅ์ ์ ํ๋ ํ์ด์ง๋ก ๋ณต๊ตฌํฉ๋๋ค. ํ์ด์ง๋ ์ต๋ 128๊ฐยทํต์ 1MiB์ด๋ฉฐ ํฐ ๋จ์ผ ๊ธฐ๋ก์ ๊ธฐ์กด heartbeat ์ํ๊น์ง ํ์ฉํฉ๋๋ค. ์คํจํ ํ์ด์ง๋ ์ฌ์๋ํ๊ณ ์ ์ฒด ์ด๋ ฅ์ ํ๋ก์ธ์ค ๋งต์ ๋ค์ ์ ์ฌํ์ง ์์ต๋๋ค. ์ผ์์ ์ธ ํต์ ์คํจ๋ง์ผ๋ก ์ ์ฒด ์ฌ์ ์ก์ ์์ํ์ง ์์ต๋๋ค. ๋ณต์ฌํ DB ํค๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฌ์ ์ก์ ์ด์ด๊ฐ๋ฉฐ ๋คํธ์ํฌ ์ ์ก ์ค ์ฝ๊ธฐ ํธ๋์ญ์
์ ์ ์งํ์ง ์์ต๋๋ค. ์ ๊ฑฐ๋ ๋
ธ๋ ID๋ ๋์คํฌ ์ธ๋ฑ์ค ์กฐํ๋ก ๊ณ์ ์ค๋ณต ์์ฑ์ ๊ฑฐ๋ถํ๋ฉฐ Agent ์ฌ์์ ๋ค์๋ ์ ์ง๋ฉ๋๋ค. ๊ธฐ์กด JSON ์ด๋ ฅ์ ์์ ์ ์ปจํ
์ด๋ ์ ๋ฆฌ ์ ์ ์๋ ๋ณํํ๊ณ ๋์กฐ๊ฐ ๋๋ ๋ฐฑ์
ํ์ผ์ ์ ์ง์ ์ผ๋ก ์ ๋ฆฌํฉ๋๋ค. ๋ณํ๋ ์ด๋ ฅ์๋ ํธํ๋๋ Agent ๋ฒ์ ์ด ํ์ํฉ๋๋ค. ์ด๋ ฅ ์ด์ ์ค๋ช
์ ์ฐธ๊ณ ํ์ญ์์ค. ์คํ ์ธ๋ ์ฐจ๋จ ์ ๋ณด๋ ๋ฉ๋ชจ๋ฆฌ์ 128๊ฐ๋ฅผ ์บ์ํ๊ณ ๋๋จธ์ง๋ peer-history/fences/์ ๋ณด๊ดํฉ๋๋ค. ์ค๋๋ stop ์์ฒญ์ด ์ ์ฅ๋ ์ฐจ๋จ ์ธ๋๋ฅผ ๋ฎ์ถ ์ ์์ผ๋ฉฐ ์ ์ฒด ์ ์ง๋ ์ด๋ฏธ ๋ฉ๋ชจ๋ฆฌ์์ ์ ๊ฑฐํ run๊น์ง ์ฐจ๋จํฉ๋๋ค.
Controller ํ์ธยท๋ก์ปฌ ์ ๋ฆฌ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ข
๋ฃ ๊ธฐ๋ก ๋๋ ์ด๋ฒคํธ ํ ์ง์
์ ๊ธฐ๋ค๋ฆฌ๋ ์ข
๋ฃ ํ์์ด ๊ฐ๊ฐ 4,096๊ฐ์ ๋๋ฌํ๋ฉด ์ Peer ์์ฑ์ Retry-After: 1๊ณผ ํจ๊ป 503์ ๋ฐํํฉ๋๋ค. ๊ธฐ์กด Peer์ ๋ฏธ์ ๋ฌ ์ฆ๊ฑฐ๋ ์ ์งํ๊ณ Docker ์ ๊ฑฐ ์คํจ๋ ๊ณ์ ์ฉ๋์ ์ ์ ํฉ๋๋ค. ์ด๋ ฅ ์กฐํยท์ ์ฅ I/O๋ Agent ์ํ ์ ๊ธ ๋ฐ์์ ์ํํ๋ฉฐ, ์ฐจ๋จ/์ด๋ ฅ ๋ณ๊ฒฝ ๋ฒํธ๋ฅผ ์ฌํ์ธํ์ฌ ๋์คํฌ ์กฐํ์ ์ ๋ฆฌ๊ฐ ๊ต์ฐจํ ๋ ์ค๋๋ ์์ฑ ์์ฒญ์ด ํต๊ณผํ์ง ๋ชปํ๊ฒ ํฉ๋๋ค.
telemetry ์์ฒญ์ ์ด๋ฒคํธ 5000๊ฐ์ JSON ๋ณธ๋ฌธ 10 MiB๋ก ์ ํ๋ฉ๋๋ค. Peer์ Agent๋ ์ด์ค์ผ์ดํ์ envelope๋ฅผ ํฌํจํ ์ธ์ฝ๋ฉ ๋ฐ์ดํธ ์๋ก batch๋ฅผ ๋๋๋ฉฐ, ์ฌ์๋์๋ ์๋ณธ ์์์ ์ด๋ฒคํธ ์๋ณ์๋ฅผ ์ ์งํฉ๋๋ค. ์๋ฝ๋ ์๋ถ๋ถ์ ์ ๊ฑฐํ ํ ๋๋จธ์ง๋ฅผ ์ ์กํฉ๋๋ค. ๋ ์์ ์๋ admission ์ ์ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ๊ฒ์ฌํฉ๋๋ค. ๋จ์ผ ์ด๋ฒคํธ๊ฐ ์ธ์ฝ๋ฉ๋ 10 MiB batch์ ๋ค์ด๊ฐ ์ ์์ผ๋ฉด 413์ ๋ฐํํ๋ฉฐ ํด๋น ์์ฒญ์ ์ด๋ฒคํธ๋ ํ๋๋ ์๋ฝํ์ง ์์ต๋๋ค. Agent๋ ์์ ์ ์๋ณ์๋ก ์ ๊ทํํ ๋ค ๊ฒ์ฌํฉ๋๋ค. Controller์ ์ง์ ์ ์ถํ ์ด๋ฒคํธ๋ ์ด ๊ฒ์ฌ๋ฅผ ๊ฑฐ์น๋ฏ๋ก ์ ์ฅ ๋ถ์์์ ์ฝ์ ์ ์๋ ๊ณผ๋ ๋ก๊ทธ ํ์ ๋ง๋ค์ง ์์ต๋๋ค.
Controller๋ ๋์ฝ๋ฉ๋ถํฐ ์๊ตฌ ์ ์ฅ๊น์ง telemetry ์์ฒญ์ ์ต๋ ๋ ๊ฐ ์๋ฝํฉ๋๋ค. ์ถ๊ฐ ์์ฒญ์ ์ต๋ 64๊ฐ๊น์ง ๋ณธ๋ฌธ์ ์ฝ์ง ์์ ์ฑ ์ต๋ 1์ด ๋๊ธฐํ๋ฉฐ, ์ทจ์๋๋ฉด ๋๊ธฐ๋ฅผ ํด์ ํฉ๋๋ค. ํฌํ ์ 503, Retry-After: 1์ ๋ฐํํ๊ณ ์์ ํ์ธ์ ํ์ง ์์ผ๋ฏ๋ก Agent๋ ํด๋น batch๋ฅผ ๋ณด๊ดํ๊ณ ์ฌ์๋ํฉ๋๋ค. ์ ์ฅ์ ์์ํ ์์ฒญ์ ํด๋ผ์ด์ธํธ ์๊ฐ ์ด๊ณผ ํ ์๋ฃ๋ ์ ์์ง๋ง ์ด๋ฒคํธ ์๋ณ์๋ก ์ฌ์๋์ ์ด์ค ์ง๊ณ๋ฅผ ๋ง์ต๋๋ค. ์ด ์ ํ์ ๋์์ ๋์ฝ๋ฉํ ๋ณธ๋ฌธ์ ์๋ฅผ ์ ํํ๋ฉฐ ์ ์ฒด Go heap ์ํ์ ์๋๋๋ค.
Agent๋ ์์ ํ์ธ ์ ์ <agent-data-dir>/telemetry-spool/์ telemetry batch๋ฅผ ์๊ตฌ ์ ์ฅํฉ๋๋ค. ํ์ธ๋ ์๋ถ๋ถ์ cursor๋ฅผ ์ ์ฅํ์ฌ ์ฌ์์ ์ ๋๋จธ์ง๋ฅผ ์ฌ์ ์กํ๊ณ Controller๋ ๋ก์ปฌ ์ด๋ฒคํธ batch๋ฅผ ๋์คํฌ์ ๋๊ธฐํํ ๋ค ์์ ํ์ธํฉ๋๋ค. Agent ๊ต์ฒด ์ ๋ฐ์ดํฐ volume์ ์ ์งํด์ผ ํฉ๋๋ค. ์ต์ ํ ๋ฒ ์ ๋ฌ ๋ฐฉ์์ด๋ฏ๋ก ์ฌ์ ์ก ๋ ์ด๋ฒคํธ ID๋ฅผ ์ ์งํ๋ฉฐ, Peer์์ ์๋ฝํ์ง ๋ชปํ ์ด๋ฒคํธ๋ ์์ด๋ฒ๋ฆฐ volume์ ์๋ฃ๋ ๋ณต์ํ์ง ๋ชปํฉ๋๋ค.
Spool ๋ณต๊ตฌ๋ ํ์ผ ์์น/Run ์ธ๋ฑ์ค์ ์ต๋ 5,000๊ฐ / ์ง๋ ฌํ ๊ธฐ์ค 1 MiB ์ ์ก ๊ตฌ๊ฐ๋ง ๋ฉ๋ชจ๋ฆฌ์ ๋๋ฉฐ, ๊ฐ๋ณ์ ์ผ๋ก ์ ํจํ ํฐ ์ด๋ฒคํธ ํ๋๋ ๊ตฌ๊ฐ ํฌ๊ธฐ๋ฅผ ๋์ ์ ์์ต๋๋ค. telemetry ๋์ฝ๋ฉยท์ ์ฅ์ ๋์ 2๊ฐ๋ก ์ ํํ๊ณ , ์ถ๊ฐ 64๊ฐ ์์ฒญ๊น์ง๋ง ๋ณธ๋ฌธ์ ์ฝ์ง ์๊ณ ์ต๋ 1์ด ๋๊ธฐํฉ๋๋ค. ๋์ฝ๋ ํฌํ ๋๋ ์ batch๊ฐ ๋๊ธฐ๋ 50,000๊ฐ / 256 MiB๋ฅผ ๋๊ธฐ๋ฉด 503๊ณผ Retry-After๋ฅผ ๋ฐํํ๊ณ ์ด๋ฏธ ์๋ฝํ ๋์คํฌยท์ ์ก ์ค ์๋ฃ๋ ๋ณด์กดํฉ๋๋ค. ๋๊ธฐ๋์ด ๊ฐ๋ ์ฐฌ ๋์ ์ Peer ๋ฐฐ์น๋ ์ผ์ ์ค๋จํฉ๋๋ค. ๊ธฐ์กด ์คํ Peer์ ์ต์ข
์ฆ๊ฑฐ๋ ์ผ์์ ์ผ๋ก ํ๋๋ฅผ ๋์ ์ ์๊ณ ๊ณผ๊ฑฐ์ ๋ ํฐ ์ ์ฒด๋ ์ญ์ ํ์ง ์๊ณ ์ ๋ฌํฉ๋๋ค. Run drain์ ์์ง ๋์คํฌ์ ๋จ์ ํด๋น Run ์ด๋ฒคํธ๊น์ง ํ์ธํฉ๋๋ค.
POST /api/v1/nodes์ ์
์ฅ ์ ๊ฑฐ์ ์๋ X-KPL-Admission-Retry: not-created์ Retry-After๋ฅผ ๋ถ์
๋๋ค. Controller๋ ์์ฝ์ ๋ฐํํ๊ณ ํด๋น Agent๋ฅผ ์ ์ ์ ์ธํ ๋ค ์๋๋ฆฌ์ค context ์์์ ์ฌ์๋ํฉ๋๋ค. ๋ฏธ์ง์ ๋ฐฐ์น๋ ๋ค๋ฅธ Agent๋ฅผ ์ฌ์ฉํ ์ ์๊ณ , ์ง์ /single-agent ๋ฐฐ์น๋ ๋์์ ์ ์งํฉ๋๋ค. ์์ฐจ ์
๋ฐ์ดํธ ์ค์๋ ๊ธฐ์กด telemetryยท์ข
๋ฃ ์ฆ๊ฑฐ ์ ์ฒด ์ค๋ฅ ๋ ์ข
๋ฅ๋ Retry-After๊ฐ ์์ ๋ ์ธ์ํฉ๋๋ค. ์ผ๋ฐ 503/timeout์ ๋ฌด์กฐ๊ฑด ์ฌ๋ฐฐ์นํ์ง ์์ต๋๋ค.
์ spool์ 4 MiB ๋ชฉํ .jsonl ํ์ผ์ batch๋ฅผ ๋ชจ์ผ๊ณ ์ฒดํฌ์ฌ ACK journal์ ์ฌ์ฉํ๋ฉฐ, ๊ธฐ์กด .json๋ ๋ณต๊ตฌํฉ๋๋ค. format-v2.json ํ์์ผ๋ก ๊ตฌ๋ฒ์ Agent๊ฐ ์ ํ์์ ๋ฏธ์ ๋ฌ ์๋ฃ๋ฅผ ๋ฌด์ํ์ง ๋ชปํ๋๋ก ํฉ๋๋ค. ์ ๋ฌ์ ๋ง์น ์ ์ ์ข
๋ฃ์์ ํ์๊ณผ ๋น ํ์ฑ ํ์ผ์ ์ ๊ฑฐํฉ๋๋ค.
Agent ์ ์ ์ข
๋ฃ ๋๋ DELETE /api/v1/nodes์ telemetry drain์ ๋ง์ง๋ง Peer ์ด๋ฒคํธ๋ฅผ ํฌํจํด ๋๊ธฐ ํ์ ์ด๋ฏธ ์ ์ก ์ค์ธ batch ๋ชจ๋ Controller์ ์์ ํ์ธ์ ๋ฐ์ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ์คํจํ batch๋ ์์๋ฅผ ์ ์งํด ์ฌ์๋ํ๋ฉฐ, ์ ํ ์๊ฐ ๋ด ์์ ํ์ธ์ ์๋ฃํ์ง ๋ชปํ๋ฉด drain ์คํจ๋ฅผ ๋ณด๊ณ ํฉ๋๋ค.
JSON ๋ณธ๋ฌธ์๋ ๊ฐ ํ๋๋ง ์์ด์ผ ํฉ๋๋ค. ๋ณธ๋ฌธ ํ๋ ๋ด์ ํํ ๊ณต๋ฐฑ์ ํ์ฉํ๋ฉฐ, ๋ ๋ฒ์งธ JSON ๊ฐยทํํ ์ฐ๋ ๊ธฐ ๋ฐ์ดํฐยท๋์ฝ๋ ๋ณธ๋ฌธ ํ๋ ์ด๊ณผ๋ 400์ ๋ฐํํฉ๋๋ค. Controller/Agent์ ์ผ๋ฐ JSON handler๋ 10 MiB, Peer /publish๋ 1 MiB, /mesh-freeze๋ 4 KiB ํ๋๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์๋๋ฆฌ์ค ์์ฒญ envelope์๋ ์์์ ์ค๋ช
ํ ๋ณ๋ ํ๋๊ฐ ์ ์ฉ๋ฉ๋๋ค. Peer ๋ด๋ถ์์ ์์ฑ๋ ์ด๋ฒคํธ๊ฐ JSON์ผ๋ก ์ธ์ฝ๋ฉ๋์ง ์๊ฑฐ๋ ๋จ์ผ batch ํ๋๋ฅผ ๋์ผ๋ฉด ๋ก๊ทธ์ telemetry_drop์ ์ ์ค ์๋ฅผ ๋จ๊ธฐ๊ณ , ์์ค sequence์ ๋น ๋ฒํธ๋ฅผ ์ ์งํ ์ฑ ํ์ ์ด๋ฒคํธ๋ฅผ ์ ์กํฉ๋๋ค. ๋คํธ์ํฌ ์คํจ ์์๋ ๋๊ธฐ ์ค์ธ batch๋ฅผ ๋ณด์กดํด ์ฌ์๋ํฉ๋๋ค.
Peer /publish์ 10์ด ๋ฐํ ์ ํ์๊ฐ์๋ ๋ค๋ฅธ ๋ก์ปฌ ๋ฐํ ๋ค์์ ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ๋ ํฌํจ๋ฉ๋๋ค. ์์ฒญ ์ทจ์๋ ์ ํ์๊ฐ ๋ง๋ฃ ์ ํ์ฌ ๋ฐํ์ ์ข
๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋๊ธฐ์์ ๋น ์ ธ๋์ค๋ฉฐ, gate/readiness ๋๊ธฐ ์ค์๋ 504๋ฅผ ๋ฐํํฉ๋๋ค. ๋๊ธฐ ์ค ์ทจ์๋ ์์ฒญ์ ๋ฐํํ๊ฑฐ๋ ์ฑ๊ณต publish ์ด๋ฒคํธ๋ฅผ ๋จ๊ธฐ์ง ์์ต๋๋ค. ๋ฐํ ์๊ฐ์ ๊ธฐ์กด์ฒ๋ผ gate์ readiness ๋๊ธฐ ์ดํ์ ๊ธฐ๋กํฉ๋๋ค.
Agent๋ Controller๊ฐ cleanup์ ์ฌ์ฉํ๋ ๋ค์ endpoint๋ ์ ๊ณตํฉ๋๋ค.
| Method | Agent path | ์ค๋ช |
|---|---|---|
POST |
/api/v1/runs/{runId}/drain |
ํด๋น Run์ ๋๊ธฐยท์ ์ก ์ค telemetry๊ฐ Controller์ ์์ ํ์ธ๋ ๋๊น์ง ์ต๋ 30์ด ๋๊ธฐ. ์ฑ๊ณต 204, ์คํจ 503. ๋ค๋ฅธ Run์ ์ ์ก์ ๊ธฐ๋ค๋ฆฌ์ง ์์. |
DELETE |
/api/v1/runs/{runId}/nodes?generation=N |
unsigned generation์ด ํ์์ด๋ฉฐ, run fence๋ฅผ N๊น์ง ์์์ ์ผ๋ก ๋์ด๊ณ ์ดํ generation N ์ดํ์ create๋ฅผ ๊ฑฐ๋ถํ๋ฉฐ ํด๋น generation์ ๊ธฐ์กด ๋
ธ๋๋ฅผ ์ข
๋ฃํ ๋ค 202 Accepted๋ฅผ ๋ฐํํฉ๋๋ค. |
๋ด๋ถ endpoint๋ ์ด์์ API์ ๋ณ๊ฐ๋ก ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค. ์์ฒญ๊ณผ snapshot์ ํ๋ ์ ์๋ internal/model/model.go, ๋์ญํญ ํ์
์ internal/model/bandwidth.go, handler๋ internal/controller/api.go์ internal/agent/api.go์ ์์ต๋๋ค.
Scoring๊ณผ inspection์ด ํ์ฑํ๋๋ฉด Peer ์ํ์ scoreSample: {observedAt, sequence, intervalSeconds, components}๋ฅผ ํฌํจํฉ๋๋ค. ๊ฐ ํญ๋ชฉ์ ํด๋น ๊ด์ธก Peer๊ฐ ํ๊ฐํ ์ ํจํ ์๋ Peer ํ๋ณธ์ {count, mean, min, max}์
๋๋ค. ํค๋ p1, p2, p3, p3b, p4, p5, p6, p7, topicCap, total์
๋๋ค. Agent๋ snapshot์ ๋ณต์ฌํด ๋ณด์กดํ๊ณ ์ค๋๋ ๊ตฌ์ฑ ํญ๋ชฉ ๋ณด๊ณ ๋ฅผ ๊ฑฐ๋ถํฉ๋๋ค. ์ ์ฒด node/network/snapshot REST์๋ ์ ๊ณตํ์ง๋ง Dashboard SSE์์๋ ๊ตฌ์ฑ ํญ๋ชฉ ์์ฝ์ ์ ์ธํฉ๋๋ค. peer_score ์ด๋ฒคํธ๋ ๊ฐ์ scoreSample์ ์์ค ์๋ณ์ยท์ด๋ฒคํธ sequence์ ํจ๊ป events.jsonl์ ์ ์ฅํ๋ฉฐ ์ต๊ทผ ๋คํธ์ํฌ ์ด๋ฒคํธ ๋ชฉ๋ก์ ์ฑ์ฐ์ง ์์ต๋๋ค. ๊ธฐ์กด ์๋ Peer๋ณ peerScores ์ด์ ๋ ์ ์งํฉ๋๋ค. ์ด ๊ฐ์ ์์ฝ ํต๊ณ์ด๋ฉฐ ๊ฐ๋ณ ์๋ Peerยทtopic ์์ ์ ์ฒด ํ๋ ฌ์ ์ ์ฅํ์ง๋ ์์ต๋๋ค.
์ ํ์ ํ๋ณธ sequence๋ Peer ํ๋ก์ธ์ค ์์์ ์ฆ๊ฐํ๋ ์์ inspection ์๋ฒ์ด๋ฉฐ ๋ฐ๊นฅ ์ด๋ฒคํธ์ sequence์ ๋
๋ฆฝ์ ์
๋๋ค. Agent๋ ์ด ๊ฐ์ผ๋ก Controller ์๊ณ offset์ด ๋ค๋ก ๋ณด์ ๋ ๋ค์๋ ๋ ์ต์ ์ธ ๊ด์ธก๊ณผ ๋น snapshot์ ๋ฐ์๋ค์
๋๋ค. observedAt์ ๋ณด์ ํ snapshot ์๊ฐ์ ์ ์งํฉ๋๋ค. ์๋ฒ์ด ์๊ฑฐ๋ 0์ธ ๊ธฐ์กด ํ๋ณธ์ ์๋ฒ ์๋ ํ๋ณธ์ด ๋์ฐฉํ ๋๊น์ง observedAt์ผ๋ก ์ ๋ ฌํ๋ฉฐ, ์๋ฒ ์๋ ํ๋ณธ์ ๋ฎ์ด์ฐ์ง ๋ชปํฉ๋๋ค. ์ Peer ํ๋ก์ธ์ค๋ Agent๊ฐ ๊ด๋ฆฌํ๋ ์ํ ์๋ช
๋ ์๋ก ์์ํฉ๋๋ค.
์๋๋ฆฌ์ค v3์ mesh-freeze action์ ๋ด๋ถ Bearer ์ธ์ฆ์ผ๋ก ๋์ Agent์ POST /api/v1/nodes/{nodeId}/mesh-freeze๋ฅผ ํธ์ถํฉ๋๋ค. Agent๋ ๋ด๋ถ token๊ณผ X-KPL-Node-ID: {nodeId} ํค๋๋ฅผ ๋ถ์ฌ ๊ฐ์ JSON์ Peer์ POST /mesh-freeze๋ก ์ ๋ฌํฉ๋๋ค. ์์ฒญ๊ณผ ์ฑ๊ณต 200 ์๋ต์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
{"runId":"run-id","generation":1}{"nodeId":"node-id","peerId":"actual-libp2p-peer-id","frozen":true}Agent๋ ์ ์ก ์ ์ readiness, GossipSub ํ์ฑํ, meshFreeze ํ์ฉ ์ค์ , ์ ํํ Runยทgeneration๊ณผ run fence๋ฅผ ๊ฒ์ฌํฉ๋๋ค. ์๋ต์ node/Peer ID๋ฅผ ํ์ธํ๊ณ ๊ฐ์ ํ๋ก์ธ์คยท์คํ ๋ฒ์๊ฐ ์ ์ง๋๋์ง ๋ค์ ํ์ธํ ๋ค ์ ์ฉ ์๋ต์ ์๋ฝํฉ๋๋ค. Peer๋ node IDยทRunยทgeneration ์ผ์น๋ฅผ ์๊ตฌํฉ๋๋ค. ์ง์ฐ๋ ์์ฒญ์ด๋ ์ฌ์ฌ์ฉ๋ ์ปจํ
์ด๋ ์ฃผ์๋ก ๋ค๋ฅธ Peer๋ฅผ ๋๊ฒฐํ์ง ์๋๋ก ํ๋ ๊ฒ์ฌ์
๋๋ค. ์ฑ๊ณต์ ๋ก์ปฌ PubSub ์ด๋ฒคํธ ๋ฃจํ๊ฐ ๋จ๋ฐฉํฅยท๋ฉฑ๋ฑ ๋๊ฒฐ์ ์ ์ฉํ๋ค๋ ๋ป์ด๋ฉฐ ์ฌ๋ฌ Peer์ ๋์ ์ ์ฉ์ ๋ณด์ฅํ์ง ์์ต๋๋ค. ๊ณ์๋๋ ํ ํด๋ก์งยท๋ฉ์์ง ๋์์ ํ๋กํ ์ฝ ์ ์๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค.
์๋๋ฆฌ์ค timeout์ ์ ์ฒด ์ ํ ๋์์ ์ ์ก๊ณผ ์ ์ฉ ์๋ต์ ํจ๊ป ์ ํํฉ๋๋ค. ๊ฐ AgentโPeer ์์ฒญ๊ณผ Peer handler์ ์ ํ์ ๊ณ์ 10์ด์ด๋ฉฐ ์๋๋ฆฌ์ค timeout์ ๋๋ ค๋ ๊ฐ๋ณ ์ ํ์ ๋์ด๋์ง ์์ต๋๋ค. ์ทจ์๋ ์ ์ด ์์ฒญ์ ๋ฐ๋ผ ์ ๋ฌ๋์ด ์ด๋ฒคํธ ๋ฃจํ์ ๋๊ธฐ๋ฅผ ํด์ ํฉ๋๋ค.
Agent๋ ์๋ชป๋ ์
๋ ฅ์ด๋ ๋๋ฝ๋ runId์ 400, ๋์ ๊ฒ์ฌยท์ ๋ฌยท์ ์ฉ ์๋ต ํ์ธ ์คํจ์ 502๋ฅผ ๋ฐํํฉ๋๋ค. Peer๋ ์๋ชป๋๊ฑฐ๋ ์ ์ ์๋ JSON ํ๋์ 400, ์๋ณ์ ๋๋ ์ค์ ๋ถ์ผ์น์ 409, ์ข
๋ฃ๋ ์ทจ์์ 503, 10์ด ์ ์ฉ ์ ํ์๊ฐ ๋ง๋ฃ์ 504๋ฅผ ๋ฐํํฉ๋๋ค. ๋ endpoint๋ ๋ด๋ถ ์ธ์ฆ ๋๋ฝยท๋ถ์ผ์น์ 401์ ๋ฐํํ๊ณ POST๋ฅผ ์๊ตฌํ๋ฉฐ ๋ค๋ฅธ method์๋ 405๋ฅผ ๋ฐํํฉ๋๋ค. ์ ์ฉ ํ ์๋ต์ด ์ ์ค๋๋ฉด ์์ฒญ์ด ์คํจํ์ด๋ Peer๋ ๋๊ฒฐ๋ ์ํ์ผ ์ ์์ต๋๋ค. ์ฌ์๋๋ ๋ฉฑ๋ฑ์ด๋ฉฐ rollback์ด๋ ๋๊ฒฐ ํด์ ๋ ์์ต๋๋ค.
Node metadata์ ๋ฌธ์์ด ๊ฐ meshFreezeEnabled๋ ์ค์ ๋ ํ์ฉ ์ฌ๋ถ, meshFrozen์ ์ ์ฉ ํ์ธ ์ํ๋ฅผ ๋ํ๋
๋๋ค. meshFrozen์ด true๊ฐ ๋๋ฉด ์ดํ ์ํ ๋ณด๊ณ ๊ฐ ์ด๋ฅผ ๋๋๋ฆฌ์ง ๋ชปํฉ๋๋ค. Peer๋ ์ฒ์ ๋๊ฒฐ์ ํ์ธํ ๋ fields.frozen: true, scope: "peer", membership: "pinned"๋ฅผ ํฌํจํ mesh_freeze ์ด๋ฒคํธ๋ฅผ ๋ด๋ณด๋ด๋ฉฐ ๋ฐ๋ณต ์ฑ๊ณต ์ ์ด๋ฒคํธ๋ฅผ ์ค๋ณต ์์ฑํ์ง ์์ต๋๋ค. ์ผ๋ฐ telemetry์ ์ ๋ฌยท์ ์ค ๊ฒฝ๊ณ๋ฅผ ๋ฐ๋ฆ
๋๋ค. ์์ฒญยท์๋ต ํ์
์ internal/model/mesh_freeze.go์ ์์ต๋๋ค.
์๋๋ฆฌ์ค v3์ topology๋ Agent์ POST /api/v1/nodes/{nodeId}/topology๋ฅผ ํธ์ถํ๊ณ Agent๊ฐ Peer์ POST /topology๋ก ์ ๋ฌํฉ๋๋ค. ๋ด๋ถ Bearer ์ธ์ฆ, X-KPL-Node-ID, ์ ํํ Runยทgeneration, readiness์ run fence ๊ฒ์ฌ๋ mesh-freeze์ ๊ฐ์ต๋๋ค. ๋ endpoint๋ JSON ๊ฐ ํ๋๋ง ํ์ฉํ๊ณ ์ ์ ์๋ ํ๋๋ฅผ ๊ฑฐ๋ถํ๋ฉฐ ์์ฒญ๊ณผ ์๋ต์ 1 MiB๋ก ์ ํํฉ๋๋ค.
{
"runId": "run-id",
"generation": 0,
"topologyId": "controller-generated-sha256",
"stage": "prepare",
"topic": "kpl/graph",
"neighbors": [{"peerId": "actual-libp2p-peer-id", "addresses": ["/ip4/10.0.0.2/tcp/20000"]}]
}prepare๋ ์ ์ฒด ์
๋ ฅ์ ๊ฒ์ฌํ๊ณ ํ์ํ ์ฐ๊ฒฐ๊ณผ PubSub ๊ตฌ๋
์ ํ์ธํ ๋ค ์ค๋น๋ ๊ณํ ํ๋๋ฅผ ๋ณด๊ดํ๋ฉฐ ๋ฉ์๋ฅผ ์ค์นํ์ง ์์ต๋๋ค. ๋ชจ๋ ๋์์ด ์ค๋น๋๋ฉด ๊ฐ์ ๊ณํ IDยทํ ํฝยท์ด์ ๋ชฉ๋ก์ apply๊ฐ ์ ํํ ํ ํฝ ๋ฉ์๋ฅผ ์ค์นํ๊ณ ๋ชจ๋ ๋ก์ปฌ ํ ํฝ ๋ฉ์๋ฅผ ๋๊ฒฐํฉ๋๋ค. topologyId๋ ์ ์ฒด ๊ทธ๋ํ์ Peer ์คํ ์ธ๋๋ฅผ ์๋ณํ๋ฉฐ ๋๋ฉ์ธ ์ ์ฒด๊ฐ ๊ณต์ ํฉ๋๋ค. ์๊ธฐ ์์ ยท์ค๋ณต ์ด์๊ณผ ์๋ชป๋๊ฑฐ๋ ๋ค๋ฅธ Peer๋ฅผ ๊ฐ๋ฆฌํค๋ /p2p ์ฃผ์ suffix๋ ๊ฑฐ๋ถํฉ๋๋ค. ํ Peer์ ์ด์์ ์ต๋ 9,999๊ฐ, ์ด์๋ณ ์ฃผ์๋ 1โ32๊ฐ, ์ฃผ์ ๊ธธ์ด๋ ์ต๋ 2,048 byte์
๋๋ค.
์ฑ๊ณต 200 ์๋ต์ {nodeId, peerId, topologyId, stage, topic, frozen, neighbors}์ด๋ฉฐ neighbors๋ ์ ํํ Peer ID ๋ชฉ๋ก์ ์ ๋ ฌํ ๊ฐ์
๋๋ค. Apply ์๋ต์ frozen: true์ฌ์ผ ํฉ๋๋ค. Agent์ Controller๋ ์๋ณ์ยท์ด์ ๋ชฉ๋ก์ ๊ฒ์ฌํ ๋ค ๊ฐ์ Peer ์คํ ์ธ๋์ธ์ง ๋ค์ ํ์ธํฉ๋๋ค. Peer ์์
์ ํ์ 30์ด์ด๊ณ , ํ์ ๋จ๊ณ์ timeout ์๋ต์ ๋ฐ์ ์ฌ์ ๋ฅผ ๋์ด AgentโPeer ์์ฒญ์ 35์ด, ControllerโAgent ์์ฒญ์ 40์ด๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค. ์ ์ฒด ์๋๋ฆฌ์ค timeout์ด ๋ ์งง์ผ๋ฉด ํด๋น ์ ํ์ ์ฐ์ ํฉ๋๋ค. ์๋ต ์ ์ค ๋ค ์ด๋ฏธ ์ ์ฉํ ๋์ผ ๊ณํ์ ๋ช
์์ ์ผ๋ก ๋ค์ ์ ์ถํ๋ ๊ฒ์ ํ์ฉํ๋ฉฐ, ๋ฌผ๋ฆฌ ๋งํฌ๊ฐ ์ฌ๋ผ์ก์ด๋ ๋ฉค๋ฒ์ญ ์ผ์น ์ ์ฑ๊ณตํฉ๋๋ค. ๋ค๋ฅธ ์ ์ฉ ๊ณํ์ ์ถฉ๋์
๋๋ค. Prepare ์ฑ๊ณต์ ์๊ฒฉ ์ํ๋ฅผ ์์ฝํ์ง ์์ผ๋ฏ๋ก apply์์ ํ์ฌ ์กฐ๊ฑด์ ๋ค์ ๊ฒ์ฌํฉ๋๋ค.
Controller๋ Peer๋ณ ์ค๋น ๋ช
๋ น์ ์ต๋ ์ธ ๋ฒ(์ต์ด ์์ฒญ๊ณผ ๋ ๋ฒ์ ์ฌ์๋) ๋ณด๋
๋๋ค. ์ผ์์ ์ธ HTTP 503/504, ๋คํธ์ํฌ ์ค๋ฅ, ๊ฐ๋ณ ์์ฒญ timeout๋ง ์ฌ์๋ํฉ๋๋ค. ์ฌ์๋ ์ ๊ฐ๊ฐ 250 ms์ 500 ms๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ์ทจ์ ์ ๋๊ธฐ๋ ์ข
๋ฃํฉ๋๋ค. ๋งค ์๋๋ง๋ค ์ ํํ Peer์ ์คํ ์ธ๋๋ฅผ ๋ค์ ๊ฒ์ฌํ๊ณ ๊ฐ์ ๊ณํ์ ๋ณด๋
๋๋ค. ๋ชจ๋ ์๋๋ ๊ฐ์ ์ ์ฒด phase ์ ํ์๊ฐ์ ๊ณต์ ํฉ๋๋ค. ๊ฒ์ฆ ์ค๋ฅ, Peer 409 ๊ฐ์ ์๊ตฌ ์ถฉ๋๊ณผ ์๋ชป๋ ์ ์ฉ ์๋ต์ ์ฌ์๋ํ์ง ์์ต๋๋ค. ์ ํํ ๊ณํ์ prepare ์๋ต์ ๋ชจ๋ ๋์์์ ๋ฐ์ ๋ค์๋ง apply๋ฅผ ์์ํ๋ฉฐ, apply๋ ์๋ ์ฌ์๋ํ์ง ์์ต๋๋ค.
์ค๋น ์ค ๊ฐ Peer๋ ์ต๋ ๋ค ์ด์์ ๋์์ ์ฐ๊ฒฐํฉ๋๋ค. ์ผ์์ ์ธ ์ฐ๊ฒฐ ์คํจ๋ ๊ธฐ์กด ๋ช ๋ น ์ ํ์๊ฐ ์์์ ์ฌ์๋ํ๋ฉฐ, ๋๊ธฐ ๊ฐ๊ฒฉ์ 250 ms๋ถํฐ ์ต๋ 2์ด๊น์ง ๋์ด๋ฉ๋๋ค. ์ฒซ ์๋์์ libp2p dial backoff๊ฐ ๋ฐ์ํ๋ฉด ์ฌ์๋ ์ ์ ํด๋น ์ด์์ backoff๋ฅผ ํ ๋ฒ ํด์ ํฉ๋๋ค. ์ดํ ์๋์์ ๋ฐ์ํ backoff๋ ์ ์งํ๋ฉฐ ๋ค๋ฅธ Peer๋ ์ ์ญ ์ฐ๊ฒฐ ์ค์ ์ ๋ฐ๊พธ์ง ์์ต๋๋ค. ์ทจ์ ์ ์ฌ์๋ ๋๊ธฐ๋ ์ข ๋ฃํ๊ณ , ์ค์ ํ transport ์ฐ๊ฒฐ timeout์ ๊ณ์ ์ ์ฉํฉ๋๋ค. ์ดํ backoff๊ฐ ๋ฐ์ํด๋ Peer์ timeout ์ง๋จ์๋ ์์ ํ์ธํ ์ค์ ์ฐ๊ฒฐ ์คํจ ์์ธ์ ๋ณด์กดํฉ๋๋ค. ๋๋ฌํ ์ ์๋ Peer๋ ์ฐ๊ฒฐยท์์ ํ๋ ๋ฌธ์ ๋ ์ฌ์๋๋ง์ผ๋ก ํด๊ฒฐ๋์ง ์์ต๋๋ค.
Agent๋ ์๋ชป๋ ์
๋ ฅ์ 400, ๋์ ๊ฒ์ฌ ์คํจยท์๊ตฌ Peer ์ค๋ฅยท์๋ชป๋ ์ ์ฉ ์๋ต์ 502๋ฅผ ๋ฐํํฉ๋๋ค. Peer์ ์ผ์์ ์ธ 503/504 ์๋ต์ ๊ทธ๋๋ก ์ ๋ฌํ๊ณ , ์ผ์์ ์ธ ์ ๋ฌ ์ค๋ฅ๋ 503, ์์ฒด ์์ฒญ timeout์ 504๋ก ๋ฐํํฉ๋๋ค. Peer๋ ์๋ชป๋ ํ๋์ 400, ์๋ณ์ยท๊ธฐ๋ฅ ํ์ฉยท๊ณํ ์ถฉ๋์ 409, ์ทจ์์ 503, timeout์ 504๋ฅผ ๋ฐํํฉ๋๋ค. ๋ endpoint ๋ชจ๋ ๋ด๋ถ ์ธ์ฆ(401)๊ณผ POST(405)๋ฅผ ์๊ตฌํฉ๋๋ค. Controller์ prepare ๋จ๊ณ ์ค๋ฅ์๋ apply๊ฐ ์์๋์ง ์์์์ ํ์ํฉ๋๋ค. ์ทจ์๋๊ฑฐ๋ ์คํจํ apply๋ ์ด๋ฏธ ์ ์ฉ๋์์ ์ ์์ผ๋ฉฐ ๋ถ์ฐ rollback์ ์ ๊ณตํ์ง ์์ต๋๋ค.
Controller์ topology_generated์๋ ๋ชจ๋ธยทํ๋ผ๋ฏธํฐยท์ค์ seedยท์์ฑ๊ธฐ ๋ฒ์ ยท๊ทธ๋ํ ํฌ๊ธฐ๋ฅผ ๊ธฐ๋กํฉ๋๋ค. topology_assignment๋ ๋
ธ๋๋ณ ์์ ์ด์ยท์ ํ์ ์ขํ์ evidence: "planned"๋ฅผ ๋ณด์กดํฉ๋๋ค. topology_stage๋ prepare/apply ์๋ต ์์ ์๋ ํ๋๋ฅผ ๊ธฐ๋กํฉ๋๋ค. Peer์ topology_applied๋ ๋ก์ปฌ์์ ํ์ธํ ๊ณํ IDยทํ ํฝยท์ด์์ ํ ๋ฒ ๊ธฐ๋กํ๋ฉฐ ์ผ๋ฐ telemetry์ ์ ๋ฌยท์ ์ค ๊ท์น์ ๋ฐ๋ฆ
๋๋ค. ์ ์ฒด ์ด์ ๋ชฉ๋ก์ ์ ์ฅ ๋ก๊ทธ์ ๋ณด์กดํ๊ณ ์ต๊ทผ ์ด๋ฒคํธ ๋ชฉ๋ก์์๋ ์ ์ธํฉ๋๋ค. ํ์ฑ ๊ฐ์ ์ ๊ณ์ ๋ฐํ์ ๋ฉ์ snapshot์ผ๋ก ๊ด์ธกํฉ๋๋ค. ํ์
์ internal/model/topology_command.go์ ์์ต๋๋ค.
topology_stage ํ๋ |
์๋ฏธ |
|---|---|
attempts |
ํด๋น ๋จ๊ณ์์ ์ค์ ๋ก ๋ณด๋ธ ControllerโAgent HTTP ์์ฒญ ์์ด๋ฉฐ ์ต์ด ์๋์ ์ฌ์๋๋ฅผ ํฌํจํฉ๋๋ค. |
retries |
์ค์ ์ถ๊ฐ ์๋ ์์ด๋ฉฐ apply๋ ํญ์ 0์
๋๋ค. |
elapsedSeconds |
ํด๋น prepare ๋๋ apply ๋จ๊ณ ์์๋ถํฐ ๊ฒฝ๊ณผํ ์ด์ ๋๋ค. |
timeoutSeconds |
๋์ ์ ํ ์์์ ๊ธฐ์ค์ผ๋ก ์ ์ฒด phase์ ์ ์ฉํ ์ ํจ ํ์ฉ ์๊ฐ(์ด)์ ๋๋ค. ์์ context ์ ํ์๊ฐ์ด ๋ ์งง์ผ๋ฉด ๊ทธ ๊ฐ์ ์ฐ์ ํฉ๋๋ค. |
timeoutScope |
Timeout ์คํจ ์ ์ ํ์ ์ผ๋ก ๊ธฐ๋กํฉ๋๋ค. ์ ์ฒด phase ์ ํ์๊ฐ ๋ง๋ฃ๋ phase, ๊ฐ๋ณ ์์ฒญ ์ ํ์๊ฐ ๋ง๋ฃ ๋๋ Agent 504๋ command์
๋๋ค. ๋ ๋ค ํด๋นํ๋ฉด phase๋ฅผ ์ฐ์ ํฉ๋๋ค. |
Scenario v3์ profile schedules๋ Agent์ POST /api/v1/nodes/{nodeId}/profile์ ํธ์ถํ๊ณ Agent๋ Peer POST /profile๋ก ์ ๋ฌํฉ๋๋ค. ๋ endpoint๋ ๋ด๋ถ ์ธ์ฆยทPOSTยท๋จ์ผ JSON ๊ฐ์ ์๊ตฌํ๋ฉฐ ์ ์ ์๋ ํ๋๋ฅผ ๊ฑฐ๋ถํ๊ณ ์์ฒญยท์๋ต์ 32 KiB๋ก ์ ํํฉ๋๋ค. Agent๋ X-KPL-Node-ID๋ฅผ ํฌํจํฉ๋๋ค. ๋ ๊ฒฝ๋ก๋ ์ ํํ Runยทgenerationยท์ค๋น ์ํยทPeer ๊ฐ์ฒด๋ฅผ ๊ฒ์ฌํ๊ณ Agent๋ ์ ๋ฌ ์ ํ Run fence๋ฅผ ๊ฒ์ฌํฉ๋๋ค.
์์ฒญ์ {runId, generation, revision, stage, set}์
๋๋ค. revision์ Run ์ธ๋ ๋ด์์ ์ฆ๊ฐํ๋ 1โ2147483647 ์ ์์ด๋ฉฐ stage๋ prepare ๋๋ apply์
๋๋ค. set์ ํ์
๊ณผ ํ๋๋ ์๋๋ฆฌ์ค ๋ ํผ๋ฐ์ค์ ์ ์ํฉ๋๋ค. 200 ์๋ต์ {nodeId, peerId, revision, stage, effective}์ด๋ฉฐ effective๋ ์์ฒญํ ์น์
์ ์์ ํ ๊ตฌ์ฒด์ ์ค์ ์
๋๋ค. AgentยทController๊ฐ ์์ฒญ ๊ฐ๊ณผ ๋์ ์๋ณ์๋ฅผ ํ์ธํฉ๋๋ค. Prepare๋ ์ ์ฉ ์์ด ํ ๊ฐ์ ์ค๋น ์ค์ ์ ๊ฒ์ฆยท๋ณด๊ดํฉ๋๋ค. Apply์๋ ๋์ผ revisionยทํจ์น์ ์ค๋น๊ฐ ํ์ํฉ๋๋ค. ์ฑ๊ณตํ ๋์ผ ์์ฒญ์ ๋ค์ ์๋ตํ ์ ์์ง๋ง ์ค๋๋ revision์ด๋ ๊ฐ์ revision์ ๋ค๋ฅธ ๊ฐ์ ์คํจํฉ๋๋ค. ์ ๊ท Peer๋ Run์ ์ต์ profile revision๊ณผ ํด๋น ํจ์น๋ฅผ ์์ํ๋ฏ๋ก ์ง์ฐ๋ ์ด์ ๋ช
๋ น์ด ์์ ์ค์ ์ ๋๋๋ฆฌ์ง ๋ชปํฉ๋๋ค.
Controller๋ ์ ์ฒด ๋์์ prepare ์๋ฃ ํ apply๋ฅผ ์์ํ๋ฉฐ apply๋ฅผ ์๋ ์ฌ์๋ํ์ง ์์ต๋๋ค. ๋ก์ปฌ ๋คํธ์ํฌ ๋ณ๊ฒฝ๊ณผ PubSub ๋ณ๊ฒฝ์ ๋ณ๋ ์ฐ์ฐ์ด๋ฏ๋ก ๋์ค ๋จ๊ณ ์คํจ ์ Peer ์ค์ ๋ ์ผ๋ถ๋ง ์ ์ฉ๋์ ์ ์์ต๋๋ค. Peer๋ ์คํจ๋ฅผ ๊ธฐ๋กํ๊ณ ํ์ profile ๋ช
๋ น์ ๊ฑฐ๋ถํฉ๋๋ค. ๋คํธ์ํฌ ์ฐ์ฐ์ 5์ด, Peer ์์ฒญ์ 8์ด, Agent ์ ๋ฌ์ 10์ด, Controller ์ ๋ฌ์ 12์ด ํ๋์ด๋ฉฐ ์ทจ์์ ๊ฐ ๋ณ๊ฒฝ์ timeout์ด ๋ ์งง์ผ๋ฉด ์ด๋ฅผ ๋ฐ๋ฆ
๋๋ค. Peer๋ ์๋ชป๋ ์
๋ ฅ 400, ์ถฉ๋ยท์ ์ฉ ์ค๋ฅ 409, ์ทจ์ 503, ๊ธฐํ ์ด๊ณผ 504๋ฅผ ๋ฐํํฉ๋๋ค. Agent๋ ๊ฒ์ฆยท์ ๋ฌยท์๋ต ์ค๋ฅ์ 502, ์๋ชป๋ ์
๋ ฅ์ 400์ ๋ฐํํฉ๋๋ค. ์ธ์ฆยท๋ฉ์๋ ์ค๋ฅ๋ 401ยท405์
๋๋ค.
ํ์ธ๋ Peer ์ํ๋ profileRevision, runtimeProfile, profileAppliedAt์ ์ ๊ณตํฉ๋๋ค. Agent๋ ์๋ต์ ๋ณ๊ฒฝ ์น์
์ ํฉ์น๊ณ ๋ ์๋ก์ด Peer ์ํ๋ก ์ ์ค๋ ์๋ต์ ๋ณต๊ตฌํ ์ ์์ต๋๋ค. ๋ถํ์คํ apply๋ Agent์ profilePending: true๋ฅผ ์ค์ ํ๋ฉฐ ๋คํธ์ํฌ ์ ์ฉ๋ ๋ถํ์คํ๋ฉด ํ์ธ๋ ๋๊น์ง networkPending: true๋ฅผ ์ค์ ํฉ๋๋ค. ์ด์ ์ ํ์ธํ ์ค์ ์ ๊ณผ๊ฑฐ ๊ทผ๊ฑฐ์ด๋ฉฐ ์คํจํ ๋ช
๋ น์ ๊ฒฐ๊ณผ๋ฅผ ์ฆ๋ช
ํ์ง ์์ต๋๋ค. ์ดํ shaping ๋์์ ๋ด๋ถ ์์ฑ ์์ฒญ์ networkMutable: true๋ก ์ปจํ
์ด๋ NET_ADMIN์ ์ค๋นํ๊ณ ์ด๊ธฐ ์์ revision์ profileRevision์ผ๋ก ์ ๋ฌํฉ๋๋ค. ์ค์ ์ด๋ฒคํธ๋ ์์ฒญ ๊ฐยทํ์ธ ๊ฐยท๋ถ๋ถ ์คํจ๋ฅผ ๊ตฌ๋ถํด ๋ณด์กดํฉ๋๋ค.
์ Peer๋ events.jsonl์ upstream libp2p์์ ์ค์ ์ ๊ณตํ๋ ๋ฉํ์ ๋ณด๋ฅผ ์ถ๊ฐํฉ๋๋ค. ๊ธฐ์กด publish/deliver/duplicate์ ๋ฉ์ธ Metrics ์ง๊ณ๋ ์ ์ง๋ฉ๋๋ค. messageId๋ envelope์ ์ ํ๋ฆฌ์ผ์ด์
ID ๋๋ raw์ pubsub-<hex native ID>์ด๋ฉฐ, fields.pubsubMessageId ๋ฐ ์๋ ์์ธ ID ๋ชฉ๋ก์ pubsub wire ID์ hex ํํ์
๋๋ค.
| ์ด๋ฒคํธ / ํ๋ | ์๋ฏธ |
|---|---|
send_*, recv_*, drop_*์ rpcMetadataVersion, rpcObservationId
|
๋ฉํ์ ๋ณด ํ์ ๋ฒ์ 1, ํ ๋ก์ปฌ RPC ์ฝ๋ฐฑ์ ์ฐ๊ฒฐ ID. ๊ฐ ์ด๋ฒคํธ์ eventId๋ ๋ณ๋๋ก ์ ์ง |
rpcMessageCount, rpcSubscriptionCount
|
๊ฐ์ RPC์ ํฌํจ๋ ๋ฐ์ดํฐ ๋ฉ์์งยท๊ตฌ๋ ํญ๋ชฉ์ ์ ์ฒด ๊ฐ์ |
IHAVE์ topicMessageIds
|
ํ ํฝ๋ณ ๊ด๊ณ ๋ฉ์์ง ID ๋ชฉ๋ก |
IWANT/IDONTWANT์ messageIds
|
์์ฒญยท๋น์์ฒญ ๋ฉ์์ง ID ๋ชฉ๋ก. ํด๋น ํ๋กํ ์ฝ ํญ๋ชฉ์๋ ์๋ ํ ํฝ์ด ์์ |
messageIdsComplete, omittedMessageIds
|
ID ๋ชฉ๋ก ์์ ์ฑ ๋ฐ ์ ํ์ผ๋ก ์๋ตํ ๊ฐ์. messageIdCount๋ ์ ์ฒด ๊ฐ์ |
PRUNE์ peerExchangeIdsByTopic, peerExchangeIdsComplete, omittedPeerExchangeIds
|
์ค์ trace๊ฐ ์ ๊ณตํ ํ ํฝ๋ณ ๊ตํ Peer ID ๋ฐ ๋ชฉ๋ก ์์ ์ฑ |
rpc_metadata์ direction, messages, subscriptions
|
send/recv/drop ๊ตฌ๋ถ, {topic,pubsubMessageId} ๋ชฉ๋ก, {topic,subscribe} ๋ชฉ๋ก. ๋ฐ์ดํฐยท๊ตฌ๋
๋ฉํ์ ๋ณด๊ฐ ์์ ๋๋ง ๋ณ๋ ์ด๋ฒคํธ ์์ฑ |
subscriptionsComplete, omittedSubscriptions
|
๊ตฌ๋ ๋ชฉ๋ก ์์ ์ฑ ๋ฐ ์๋ต ๊ฐ์ |
pubsub_reject์ reason, pubsubMessageId
|
libp2p๊ฐ ๋ณด๊ณ ํ ๋ฉ์์ง ๊ฑฐ๋ถ ์ฌ์ ์ ID |
deliver / duplicate์ hopwaveMetadataVersion, hopwaveSource
|
๋ฒ์ 1, ์ถ์ฒ wire. HopWave ๋ฉํ์ ๋ณด๊ฐ ์์ ๋๋ง ๊ธฐ๋ก |
hopwaveHopCountAvailable, hopwaveHopCount
|
์์๊ฐ ์๋ wire ์นด์ดํฐ์ ๊ฐ์ฉ ์ฌ๋ถ. ์ฌ์ฉํ ์ ์์ผ๋ฉด ๊ฐ์ ์๋ต. HopWave ์ ๋ฌ์์๋ ์ ๋ ๊ฒฝ๋ก ๊ธธ์ด๊ฐ ์๋ ์ํ ์นด์ดํฐ |
hopwavePropagationType |
์๋ wire enum์ eager-push, lazy-pull, unknown์ผ๋ก ํํ. enum์ด ์์ผ๋ฉด ์๋ต |
timestampSource, sourceTimestamp
|
trace ์๊ฐ์ ์ถ์ฒ์ ๋ณด์ ์ ์๋ณธ ์๊ฐ. upstream ์๊ฐ์ด ์์ผ๋ฉด peer-clock์ผ๋ก ํ์ํ๊ณ ์๋ณธ ์๊ฐ์ ๋ง๋ค์ง ์์ |
clockBasis, clockOffsetMs, clockUncertaintyMs
|
์ ํจํ Controller ๋๊ธฐํ ๊ทผ๊ฑฐ๊ฐ ์์ ๋ ์ถ๊ฐํ๋ ์๊ฐ ๋ณด์ ์ ๋ณด |
ID ์์ธ๋ ์ข
๋ฅ๋ณ ์ต๋ 8,192๊ฐ ๋ฐ hex ํฉ๊ณ 512KiB, ๊ตฌ๋
๋ชฉ๋ก์ ์ต๋ 8,192๊ฐ์
๋๋ค. ์์ธ ๋ชฉ๋ก์ด ์๋ ค๋ ํด๋น ์ด๋ฒคํธ์ RPCยทentryยทID ์ง๊ณ๋ ์ ์ฒด ๊ฐ์๋ฅผ ์ ์งํฉ๋๋ค. ์ด๋ฒคํธ ์ ์ค์ ๊ธฐ์กด telemetry_drop๊ณผ ์์ค sequence๋ก ์ถ์ ํฉ๋๋ค. ์๋ณธ payload, IWANT ๋ฐ์ ์์ธ, wire์ ์๋ RPC ์ ์ญ ID๋ ๋ง๋ค์ง ์์ต๋๋ค. Eager/Lazy๋ ์งํ ๋ฌธ์์ ๋ฉํ์ ๋ณด ์ถ์ ๊ท์น์ ์ ์ฉํฉ๋๋ค.
hopwave* ํ๋๋ ์๋ช
ํ์ง ์๋ wire ๋ณด๊ณ ๊ฐ์
๋๋ค. ํด์๊ณผ ํธํ ์๊ฑด์ HopWave๋ฅผ ๋ฐ๋ฅด๋ฉฐ ๊ธฐ์กด ๋ถ์ ์ถ์ ์ ์ ์ง๋ฉ๋๋ค. Wire ๋ฉํ์ ๋ณด๊ฐ ์๋ ๋ก๊ทธ์๋ HopWave ํ๋๋ฅผ ๋ง๋ค์ง ์์ต๋๋ค.
Controller์ ๋ชจ๋ Agent์ ๊ฐ์ KPL_USERยทKPL_PASSWORD๋ฅผ ์ค์ ํ๋ฉฐ ์์ ์ ๋ ๋ค ํ์์
๋๋ค. ๋์๋ณด๋๋ ๋จผ์ Log in ํ๋ฉด์ ์ด๊ณ , ๋ก๊ทธ์ธ ์ฑ๊ณต ์ ์์์ ์๋ฒ ์ธ์
์ ์์ฑํด HttpOnlyยทSameSite=Strict ์ฟ ํค๋ก ์๋ณํฉ๋๋ค. HTTPS์์๋ Secure ์ฟ ํค๋ฅผ ์ฌ์ฉํ๋ฉฐ ์ ๋ขฐํ ์ ์๋ reverse proxy์ X-Forwarded-Proto: https๋ ์ง์ํฉ๋๋ค. ์ธ์
์ 12์๊ฐ ๋ค ๋ง๋ฃ๋๊ณ Log out ๋๋ Controller ์ฌ์์ ์ ๋ฌดํจํ๋ฉ๋๋ค. ๋ก๊ทธ์์ยท๋ง๋ฃ ์ ํด๋น ์ธ์
์ SSE ์ฐ๊ฒฐ๋ ๋ซ์ง๋ง ์คํ ์ค ์คํ๊ณผ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋ถ์์ ๊ณ์๋ฉ๋๋ค. ์ค์ ๊ณ์ ํ๋๊ฐ ๋์๋ณด๋ ์ ์ฒด ๊ถํ์ ๊ฐ์ง๋๋ค.
๋์๋ณด๋/API ์กฐํยท๋ณ๊ฒฝ, SSE, ์๋๋ฆฌ์ค ๊ฒ์ฆ, ๋ถ์, ๋ค์ด๋ก๋๋ ๋ชจ๋ ๋ก๊ทธ์ธ ์ธ์
์ด ํ์ํฉ๋๋ค. ๋ฏธ์ธ์ฆ API๋ JSON 401์ ๋ฐํํ๋ฉฐ, HTML์ ์์ฒญํ๋ ๋ธ๋ผ์ฐ์ GET/HEAD ํ์์๋ ๊ฐ์ 401 ์ํ์ Login required ์๋ด ํ์ด์ง๋ฅผ ์ ๊ณตํฉ๋๋ค. /login-required์์๋ ์ด ์ ์์ผ๋ฉฐ ๋ก๊ทธ์ธ ํ๋ฉด๊ณผ ๋์๋ณด๋๋ก ์ด๋ํ๋ ๋งํฌ๊ฐ ์์ต๋๋ค. ๋์๋ณด๋ API/SSE์ ์ธ์
๋ง๋ฃ ์์๋ ์ด ํ์ด์ง๋ก ํ ๋ฒ ์ด๋ํ๊ณ ์ฌ์ฐ๊ฒฐ์ ์ค๋จํฉ๋๋ค. ์ฌ์ฉ์๊ฐ ์ง์ ๋ก๊ทธ์์ํ๋ฉด /login์ผ๋ก ์ด๋ํ๊ณ , ์ธ์
์์ด ๋์๋ณด๋๋ฅผ ์ฒ์ ์ด ๋๋ ๊ธฐ์กด์ฒ๋ผ /login์ผ๋ก ๋ฆฌ๋ค์ด๋ ํธํฉ๋๋ค. ์ธ์
์ ์ฌ์ฉํ๋ ๋ณ๊ฒฝ ์์ฒญ์ X-KPL-Request: dashboard ํค๋๋ ํ์ํ๋ฉฐ ๋ค๋ฅธ origin์ ์์ฒญ์ ๊ฑฐ๋ถํฉ๋๋ค. UI๋ ์ด ํค๋๋ฅผ ์๋์ผ๋ก ๋ฃ์ผ๋ฏ๋ก ์ถ๊ฐ ํ ํฐ ์
๋ ฅ์ด ์๊ณ ๋น๋ฐ๋ฒํธยท์ธ์
์ฟ ํค๋ฅผ localStorage์ ์ ์ฅํ์ง ์์ต๋๋ค. ๋ก๊ทธ์ธ์ JSON {user, password}๋ง ๋ฐ์ผ๋ฉฐ ์๋ชป๋ ๊ณ์ ์ 401, ๊ฐ์ ์ ์ IP์์ 5๋ถ ๋์ 10ํ ์คํจํ ์ดํ์๋ 429๋ฅผ ๋ฐํํฉ๋๋ค. ์ธ์
๊ณผ ์คํจ ๊ธฐ๋ก์ ๊ฐ๊ฐ ์ต๋ 1,024๊ฐ์
๋๋ค. ๋ก๊ทธ์ธ ์๋ต ์ ์ก ์ค์๋ ์ธ์
์ ๊ธ์ ์ ์งํ์ง ์์ผ๋ฏ๋ก, ์๋ต์ ๋ฐ์ง ๋ชปํ๋ ๋ก๊ทธ์ธ ํด๋ผ์ด์ธํธ๊ฐ ๋ค๋ฅธ ์ธ์
ํ์ธ์ด๋ ๋ก๊ทธ์์์ ๋ง์ง ์์ต๋๋ค.
๋ก๊ทธ์ธ ๋ฆฌ์์ค, health/์๊ฐ endpoint, /metrics, ๋ Prometheus target-discovery endpoint๋ง ๊ณต๊ฐ๋ก ์ ์งํฉ๋๋ค. ๋ด๋ถ Agent ๋ฑ๋กยทheartbeatยท์ด๋ฒคํธ์ Peer bootstrapยทdiscovery๋ ๊ณ์ ์ค์ ์์ ์ฉ๋๋ฅผ ๋ถ๋ฆฌํด ์๋ ์์ฑํ ์๋น์ค ํค๋ฅผ ์ฌ์ฉํฉ๋๋ค. Peer์๋ ๋ก๊ทธ์ธ ๋น๋ฐ๋ฒํธ ๋์ ์ด ํค๋ง ์ ๋ฌํ๋ฉฐ, ํค๋ก ๋์๋ณด๋ ๊ฒฐ๊ณผ API์ ์ ๊ทผํ๊ฑฐ๋ ์คํ์ ์์ํ ์ ์์ต๋๋ค. KPL_API_TOKEN๊ณผ --token CLI ์ต์
์ ํ๊ธฐํ์ต๋๋ค. ์๊ฒฉ ์ฆ๋ช
๋ณ๊ฒฝ ์ ์ด์ ํค๋ฅผ ์ฐ๋ ์งํ ์ค ์คํยท์์กด Peer๋ฅผ ์ ๋ฆฌํ ๋ค Controller์ Agent๋ฅผ ํจ๊ป ์ฌ๋ฐฐํฌํ์ญ์์ค. Grafana ๋ก๊ทธ์ธ์ ๋ณ๋์
๋๋ค.
REST ํด๋ผ์ด์ธํธ๋ ์๋ ์ฃผ์๋ฅผ access ์ถ๋ ฅ์ผ๋ก ๋ฐ๊พธ๊ณ ํ ๋ฒ ๋ก๊ทธ์ธํฉ๋๋ค. ๋น๊ณต๊ฐ ์ฟ ํค ํ์ผ์ ์ ์์ ๋ค์์ ์ฌ์ฌ์ฉํ์ญ์์ค.
KPL_URL=http://control-node:8080
KPL_COOKIE_JAR=$(mktemp)
read -r -p 'Username: ' KPL_USER
read -r -s -p 'Password: ' KPL_PASSWORD; printf '\n'
export KPL_USER KPL_PASSWORD
python3 -c 'import json,os; print(json.dumps({"user":os.environ["KPL_USER"],"password":os.environ["KPL_PASSWORD"]}))' |
curl --fail-with-body -c "$KPL_COOKIE_JAR" \
-H 'Content-Type: application/json' --data-binary @- "$KPL_URL/api/v1/auth/login"
unset KPL_PASSWORD
curl --fail-with-body -b "$KPL_COOKIE_JAR" "$KPL_URL/api/v1/snapshot"์์ฒญ์ ๋ง์น ๋ค ๋ก๊ทธ์์ํ๊ณ ์ฟ ํค ํ์ผ์ ์ญ์ ํฉ๋๋ค.
curl --fail-with-body -b "$KPL_COOKIE_JAR" -H 'X-KPL-Request: dashboard' \
-X POST "$KPL_URL/api/v1/auth/logout"
rm -f "$KPL_COOKIE_JAR"HTTP ์์ฒด๋ ์๊ฒฉ ์ฆ๋ช ๊ณผ ์ฟ ํค๋ฅผ ์ํธํํ์ง ์์ต๋๋ค. HTTPS ๋๋ ์ ๋ขฐ ๊ด๋ฆฌ๋ง์ ์ฌ์ฉํ๊ณ HTTPS proxy๋ forwarded protocol ํค๋๋ฅผ ๋ฎ์ด์จ์ผ ํฉ๋๋ค.
์๋๋ฆฌ์ค์ ๊ฐ์ ๋ค ๊ฐ์ง job counter๊ฐ /api/v1/snapshot๊ณผ SSE snapshot์๋ ํฌํจ๋ฉ๋๋ค. ๋์๋ณด๋๋ ๊ฐ run์ ์ด๋ฅผ ํ์ํ๋ฏ๋ก Controller ๋ก๊ทธ๋ฅผ ์ด์ง ์์๋ ์คํ ์ค, ์ฑ๊ณต, ์คํจ, ์ทจ์๋ background ์์
์๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
์๊ฐํ ๊ฐ์ด๋์์ ๋ถ์ ์๋ต, ๊ทธ๋ํ์ ๋ด๋ณด๋ด๊ธฐ ํ์์ ํ์ธํ์ญ์์ค.