- K8s deployment (2 replicas, PVC, initContainer для server_name) - Streams definitions (MM_ONLINE, MM_OFFLINE, MM_WRITE, MM_EVENTS) - Job payload schema (JSON v1 з idempotency) - Worker contract (capabilities + ack/retry) - Init streams script - Оновлено ARCHITECTURE-150-NODES.md (Control-plane vs Data-plane) TODO: Auth (nkeys), 3+ replicas для prod, worker-daemon implementation
4.1 KiB
4.1 KiB
Worker Contract v1 — Memory Module
Дата: 2026-01-10
Версія: 1.0.0
📋 Capability Registry
Кожен воркер реєструється з наступними capabilities:
{
"node_id": "node-123",
"tier": "A|B|C",
"region": "eu-west",
"trust_zone": "internal",
"hardware": {
"cpu_cores": 32,
"ram_gb": 128,
"gpu": true,
"gpu_model": "RTX 3090",
"vram_gb": 24,
"cuda_version": "13.0"
},
"capabilities": {
"max_batch": 1000,
"max_tokens": 8192,
"models": ["embed-multilingual-v3.0", "llama3:8b"],
"embedding_dim": 1024,
"supported_jobs": ["embed", "summarize", "index"]
},
"status": "ready|busy|maintenance",
"last_heartbeat": "2026-01-10T19:30:00Z"
}
Реєстрація
- Postgres (таблиця
worker_capabilities) або Consul (KV store) - Heartbeat кожні 30 секунд
- Якщо heartbeat пропущено > 90 секунд → worker вважається offline
🔄 Job Execution Flow
1. Pull Model
Воркер сам вирішує "чи брати job":
- Підписка на consumer (durable)
- Перевірка
requirementsvs власніcapabilities - Якщо підходить → бере job, інакше пропускає
2. Execution
async def execute_job(job: JobPayload):
# 1. Перевірка requirements
if not can_fulfill(job.requirements, my_capabilities):
await msg.nak() # Negative ack, не підходить
return
# 2. Виконання
try:
result = await process_job(job)
# 3. Запис результату
await write_result(job, result)
# 4. ACK
await msg.ack()
except RetryableError as e:
await msg.nak(delay=e.backoff)
except FatalError as e:
await msg.ack() # ACK щоб не retry
await log_error(job, e)
3. ACK/NAK Policy
- ACK — job виконано успішно
- NAK — job не виконано, потрібен retry
- NAK(delay) — retry з затримкою
- Timeout — якщо
ack_waitвийшов → автоматичний retry
📊 Consumer Policies
Online Consumer (Tier A)
stream: MM_ONLINE
consumer: online-worker-tier-a
ack_wait: 30s
max_ack_pending: 5000
concurrency: 50-200 (per worker)
filter: tier=A AND needs_gpu=true (для GPU jobs)
Worker Selection:
- Тільки
tier=A needs_gpu=true→ тільки GPU воркериmax_latency_msперевірка
Offline Consumer (Tier B)
stream: MM_OFFLINE
consumer: offline-worker-tier-b
ack_wait: 5-30 min
max_ack_pending: 10000
concurrency: висока, але з backpressure
Backpressure:
- Якщо online backlog росте → обмежити offline concurrency
- Preemption: offline jobs можуть бути призупинені для online
🔍 Idempotency
Обов'язково: кожен job має idempotency_key (SHA256 hash).
Перевірка:
- Перед виконанням перевірити в Postgres: чи вже виконано?
- Якщо так → повернути кешований результат
- Якщо ні → виконати та зберегти результат
TTL: idempotency keys зберігаються 7 днів.
📈 Metrics & Alerts
Worker Metrics
worker_jobs_processed_total{type, status}worker_job_duration_seconds{type, quantile}worker_gpu_utilization{node_id}worker_vram_usage_bytes{node_id}worker_errors_total{type, error_type}
NATS Metrics
nats_consumer_lag{stream, consumer}nats_redeliveries_total{stream}nats_ack_pending{stream, consumer}nats_stream_storage_bytes{stream}
Alerts → Matrix Ops Room
MM_ONLINE backlog > 1000(SLO порушення)redeliveries spike > 100/minembed p95 > 500ms(target: 300ms)disk > 80%на JetStream PVCworker offline > 2 min(Tier A)
Документ створено: 2026-01-10 19:30 CET