- Archive completed subtask plans/code reviews (04, 05+03,04, 07+03) - Add provider_pool_admission_test.go - Update edge config types, load, catalog validation - Update runtime, config refresh, service layers for admission - Update test docs and inventory - Update provider scheduling, resolution, tunnel, status modules
15 KiB
Milestone: Provider Resource Admission Ownership 정합화
위치
- Roadmap: ROADMAP.md
- Phase: PHASE.md
목표
nodes[].providers[]가 선언한 실행 resource의 capacity와 long-context slot을 여러 models[].id가 같은 provider를 참조하더라도 하나의 provider 상태로 일관되게 적용하도록 admission 소유권을 바로잡는다.
Edge는 provider 전역 lease를 실행 한도의 authoritative source로 사용하고, Node는 normalized/tunnel 경로에 같은 adapter-local 안전장치를 적용해 model alias 추가나 우회 실행이 실제 backend 동시 실행 한도를 넘지 못하게 한다.
Node transport 연결 종료는 같은 provider resource의 connectivity availability로 즉시 반영해 새 admission 대상에서 제외하고, 대기 요청과 운영 snapshot이 동일한 offline 상태로 수렴하도록 한다.
상태
[진행중]
승격 조건
- 없음
구현 잠금
- 상태: 해제
- SDD: 필요
- SDD 문서: SDD.md
- SDD 사유: provider 전역 admission 상태와 lease lifecycle, 여러 model queue의 공정한 재평가, queue config 소유권, Edge-Node 실행 경계와 live refresh 의미를 함께 변경한다.
- 잠금 해제 조건: 아래 체크리스트
- 에이전트 작업성 중심 저장소 구조 리팩터링이 완료되어 후속 구현 기준 파일 구조가 확정되어 있다.
- SDD 잠금이 해제되어 있다.
- SDD 사용자 리뷰가 없거나 승인/해결되었다.
- Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다.
- Evidence Map이 완료 시
Roadmap Completion과 최종 검증 evidence로 검증 가능하게 연결되어 있다.
- 결정 필요: 없음
범위
- Edge admission의 provider resource state를
node_id + provider_id기준 전역 상태로 두고 여러 model group이 capacity와 long-context 점유를 공유한다. - provider lease 획득·handoff·반환을 원자적이고 idempotent하게 처리하고, send 실패, terminal event/frame, cancel, 연결 종료와 node disconnect가 같은 lease를 중복 반환하거나 누락하지 않게 한다.
- lease 반환과 disconnect fencing 같은 correctness 전이는 drop 가능한 관측 event fanout에 의존하지 않고 authoritative resource lifecycle에서 직접 처리한 뒤 event를 발행한다.
- lease 반환·provider 비활성화·node 연결 해제·capacity refresh 때 model group 경계를 넘어 가장 먼저 들어온 현재 dispatch 가능한 요청부터 재평가해 starvation과 head-of-line blocking을 함께 방지한다.
- provider별 실행 속성은 provider가 소유하고 여러 후보와 model group에 공통인
max_queue와queue_timeout_ms는 Edge의 provider-pool admission policy가 소유하도록 정렬한다. provider 전역 capacity와 아직 provider가 정해지지 않은 Edge queue를 같은 상태로 혼동하지 않는다. long_context_capacity는 provider 전역 runtime slot으로 공유한다.total_context_tokens는 이번 범위에서context_window_tokens * long_context_capacity정적 설정 검증 기준으로 유지하며 요청별 KV token ledger로 확장하지 않는다.- provider snapshot이 admission과 같은 resource state에서
capacity,in_flight, long-context 점유를 읽고,queued는 SDD에서 정한 queue owner와 candidate-pressure 의미로 일관되게 계산하도록 한다. - Edge의 provider 전역 lease를 authoritative admission으로 두되, Node의 normalized
RunRequest와ProviderTunnelRequest에는 같은 adapter instance를 보호하는 local capacity gate를 별도로 둔다. - config refresh 중 capacity·long-context capacity·priority·queue·enabled 변경이 기존 lease를 잃지 않고 이후 admission과 대기 후보 재평가에 일관되게 적용되도록 한다.
- Node 프로세스 또는 Windows의 정상 종료 절차가 transport close를 보낸 경우 heartbeat timeout을 기다리지 않고 해당 Node의 모든 provider resource를 admission 후보에서 제외한다. 전원 단절·네트워크 blackhole처럼 close를 받을 수 없는 경우에만 heartbeat timeout을 fallback으로 사용한다.
- Node disconnect로 대기 요청의 live candidate가 사라지면 남은 provider로 즉시 재평가하고, 후보가 하나도 없으면 원래
queue_timeout_ms까지 대기하지 않고 명시적인 unavailable 결과로 종료한다. - 구성에는 남아 있지만 연결이 끊긴 Node/provider는 운영 snapshot에서 사라지게 하지 않고 offline/excluded 상태로 유지해 관측 상태와 admission eligibility가 같은 connectivity source of truth를 사용하도록 한다.
기능
Epic: [resource-admission] Provider 전역 Resource Lease
model group queue와 독립된 provider resource lease를 admission의 단일 source of truth로 만든다.
- [provider-state] Edge가
node_id + provider_id별 capacity와 in-flight를 하나의 provider resource state로 관리하고, 서로 다른 두models[].id가 같은 provider를 참조해도 합산 점유가 capacity를 넘지 않는다. 검증: capacity 1 provider를 공유하는 두 model group의 동시 admission에서 upstream dispatch가 한 건만 발생한다. - [lease-lifecycle] admission이 고유 provider lease를 만들고 dispatch 전 추적과 handoff 뒤 terminal lifecycle이 이를 정확히 한 번 반환한다. correctness 경로는 drop 가능한 event fanout과 분리한다. 검증: send 실패, complete/error/cancel, tunnel terminal/close와 node disconnect 경쟁 및 event subscriber 포화에서도 일반·long counter가 음수가 되거나 남지 않는다.
- [long-state] long-context capacity와 점유가 provider 전역으로 합산되고
total_context_tokens는 정적 설정 검증값으로 유지된다. 검증: 서로 다른 model group의 long 요청이 같은 provider long slot을 동시에 초과하지 않고 잘못된context_window_tokens * long_context_capacity설정은 load/refresh에서 거부된다. - [cross-group-wakeup] provider lease 반환, node disconnect, provider disable 또는 capacity refresh 후 전역 enqueue 순서상 가장 이른 dispatch 가능한 요청부터 model group 경계를 넘어 재평가된다. 검증: 한 model group의 종료가 다른 model group의 대기 요청을 깨우고, 막힌 long 요청 뒤의 실행 가능한 normal 요청도 진행하며, starvation·중복 예약·slot 누수가 없다.
- [tunnel-guard] Edge의 provider 전역 lease와 별개로 Node의 normalized 실행과 provider tunnel 실행이 같은 adapter-local capacity 안전장치를 사용한다. 검증: Edge admission을 우회한 동시 tunnel 요청에서도 두 번째 upstream provider 요청이 열리지 않고 명시적인 concurrency 결과가 반환된다.
Epic: [provider-policy] Provider Policy 의미 정렬
provider config에 선언된 정책과 실제 Edge/Node 적용 위치의 불일치를 제거한다.
- [queue-ownership] Edge의
provider_pool.max_queue와provider_pool.queue_timeout_ms가 여러 model group에 공통인 provider-pool queue policy를 소유하고 schema, compatibility, admission과 refresh 경로에서 일관되게 적용된다. provider는 capacity, long-context capacity, priority처럼 provider별 실행 속성만 소유한다. 검증: 여러 provider가 있는 model group과 하나의 provider를 공유하는 여러 model group에서 Edge 전체 pending 상한과 공통 timeout이 적용되고 first-candidate 값이 전체 정책으로 암묵 승격되지 않는다. - [snapshot-source] provider snapshot의 일반·long
in_flight가 provider lease state와 일치하고,queued/long_queued가 Edge queue에서 해당 provider를 후보로 포함하는 candidate pressure임을 명확히 한다. 검증: cross-model 실행·대기·반환 전 과정에서 lease count가 snapshot과 일치하고 multi-candidate queued 수가 실제 Edge queue 총합과 구분되는 문서화된 규칙대로 계산된다. - [refresh-consistency] capacity, long-context capacity, priority, queue policy와 enabled live refresh가 기존 lease를 보존하고 새 admission과 모든 관련 대기 요청에 즉시 반영된다. 검증: capacity를 in-flight 아래로 낮추면 기존 요청은 유지하되 새 값 아래로 회복할 때까지 추가 admission을 차단하고, capacity 증가·disable·재활성화 시 대기 후보가 고립되지 않는다.
Epic: [connectivity-availability] Node 연결 기반 Provider Availability
Node transport lifecycle을 provider resource eligibility와 운영 관측의 같은 상태 전이로 연결한다.
- [disconnect-exclusion] 등록된 client ownership/generation을 provider lease와 연결하고, 현재 owner의 정상 close 또는 disconnect만 해당 Node의 모든 provider resource를 즉시 offline/excluded로 fencing한다. stale callback이나 거절된 duplicate connection의 close는 live resource 상태와 disconnect event를 바꾸지 않는다. 정상적인 Node 프로세스 종료와 Windows 종료 절차는 heartbeat timeout을 기다리지 않으며, close를 받을 수 없는 전원·네트워크 장애만 설정된 heartbeat timeout 안에 제외한다. 검증: disconnect·reconnect·duplicate registration·admission 경쟁에서 offline generation의 새 lease/dispatch handoff가 없고 기존 lease는 정확히 한 번 반환된다.
- [disconnect-queue-resolution] authoritative disconnect 전이가 모든 관련 model queue의 live candidate를 즉시 다시 해석해 남은 provider로 fallback하고, 후보가 없어진 요청은
queue_timeout_ms까지 남겨 두지 않고 명시적인 unavailable 결과로 종료한다. 이 correctness 경로는 관측 event delivery 성공 여부에 의존하지 않는다. 검증: capacity 1 provider에 실행·대기 요청이 있는 상태에서 연결을 닫거나 node event subscriber를 포화시켜도 대기 요청이 즉시 fallback 또는 terminal 상태가 되며 queue와 reservation이 남지 않는다. - [offline-snapshot] 구성에 존재하지만 연결이 끊긴 Node/provider를 운영 snapshot에
connected=false,status=unavailable,health=offline, effective capacity/counter 0으로 유지하고, reconnect 때 같은 resource identity의 새 generation으로 available 상태를 복구한다. 검증: disconnect/reconnect 전후 status snapshot, admission candidate와 in-flight/long counter가 같은 connectivity generation에 수렴하며 model catalog entry 자체는 삭제되지 않는다.
Epic: [ownership-verification] 계약과 회귀 검증
소유권 변경이 외부 model alias와 Edge-Node 실행 경로에서 재발하지 않도록 계약과 검증 근거를 남긴다.
- [cross-model-tests] 같은 provider를 공유하는
ornith:35b와ornith-fast형태의 두 model key를 포함해 capacity, long-context, queue fairness, cancel, send 실패, graceful disconnect, heartbeat-timeout fallback, duplicate/stale disconnect, event fanout 포화, reconnect와 refresh 회귀·race 테스트가 추가되어 있다. - [contract-spec-sync] 구현 결과가 Edge Config And Runtime Refresh Contract, Edge-Node Runtime Wire Contract, Control Plane-Edge Wire Contract, OpenAI-Compatible API Contract과 관련
agent-spec에 동기화되어 있다. - [capacity-smoke] local 또는 dev-corp의 공유 provider capacity 1 smoke에서 두 model key 동시 호출 시 backend peak concurrency가 1이고, 대기 또는 다른 provider fallback 뒤 모든 provider 상태가 0으로 회복된다.
완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: SDD와 선행 리팩터링 gate는 충족되었고 기능 구현과 검증은 아직 시작되지 않았다.
- 검토 항목: 모든 기능 Task와 Acceptance Scenario evidence, 구현 잠금 해제, provider capacity 1 cross-model smoke 결과를 확인한다.
- agent-ui 상태 반영: 해당 없음
- 리뷰 코멘트: 없음
범위 제외
ornith-fast모델 catalog entry 추가, RTX5090 모델 다운로드·기동 또는 운영 환경 배포- Provider 부하 Prometheus metric과 Grafana dashboard 구현
- provider runtime launch profile, 모델 artifact 다운로드·cache·restart lifecycle 자동화
- Node 연결이 유지된 상태에서 Lemonade 등 provider endpoint를 능동 probe해 정적 config
health를 대체하는 runtime health state machine - provider
request_timeout_ms와 surfacetimeout_sec의 deadline 결합·오류 분류 재설계 - 요청별 input/output KV 사용량을 예약·반환하는 동적
total_context_tokensledger - cross-Edge 또는 cloud provider를 포함한 전역 capacity 공유
- provider별 benchmark, 품질 평가와 qualification report
작업 컨텍스트
- 관련 경로:
apps/edge/internal/service,apps/edge/internal/transport,apps/edge/internal/controlplane,apps/edge/internal/openai,apps/node/internal/node,apps/node/internal/transport,packages/go/config,apps/edge/internal/configrefresh,proto/iop/runtime.proto,proto/iop/control.proto,agent-contract/inner,agent-contract/outer,agent-spec/runtime - 표준선(선택): provider/resource capacity, long-context slot, priority처럼 provider별로 달라지는 속성은 provider가 소유하고, provider-pool queue depth와 timeout처럼 공통 적용되는 정책은 Edge가 소유한다. model group은 외부 model key와 후보 집합을 소유한다.
- 큐 배치(선택): 에이전트 작업성 중심 저장소 구조 리팩터링 뒤
- 선행 작업: 에이전트 작업성 중심 저장소 구조 리팩터링
- 후속 작업: Provider 부하 메트릭과 Live Queue Dashboard, Provider Runtime 설정과 모델 획득 오케스트레이션
- 후속 정합화 후보: Node 연결이 살아 있는 동안 provider endpoint/Lemonade 프로세스 장애를 탐지하는 runtime health probe source of truth와 provider/surface request timeout 결합 규칙은 별도 Milestone/SDD에서 다룬다.
- 확정 사항: D01은 Edge 공통 provider-pool queue policy 소유로 해결되었다. 사용자 리뷰 기록