- 모델 그룹별 큐 기반 디스패팅 로직 추가 - ModelQueue 관리자로 모델 인스턴스 큐 처리 - OpenAPI chat 및 responses 핸들러 업데이트 - edge 서비스 테스트 코드 개선
10 KiB
Plan - REFACTOR Node Queue Simplify
이 파일을 읽는 구현 에이전트에게
CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션 작성은 필수다. 구현 후 검증 명령을 실행하고 실제 출력, 구현 메모, 계획 대비 변경 사항을 채운 뒤 active 파일을 남긴 채 리뷰 준비 상태로 보고한다. 최종 판정, log rename, complete.log, archive 이동은 code-review-skill 전용이다. 구현 중 사용자만 결정할 수 있는 범위 변경, 외부 환경/secret, 또는 scope conflict가 생기면 chat에서 묻지 말고 review stub의 사용자 리뷰 요청 섹션에 근거와 재개 조건을 남긴다.
배경
현재 Node는 provider-scoped FIFO admission queue와 node-wide global gate를 소유한다. 현재 마일스톤의 목표는 queue owner를 Edge로 옮기는 것이므로, Node는 dispatch된 실행을 수행하고 상태를 보고하는 역할로 단순화되어야 한다. Edge queue core가 먼저 들어간 뒤 Node-local FIFO는 제거하거나 over-dispatch 안전장치 수준으로 축소한다.
사용자 리뷰 요청 흐름
구현 중 blocker는 active review stub의 사용자 리뷰 요청 섹션에 기록한다. 구현 에이전트는 사용자에게 직접 질문하거나 선택지를 제시하지 않는다. code-review가 해당 요청을 검증하고 필요할 때만 USER_REVIEW.md를 작성한다.
Roadmap Targets
- Milestone:
agent-roadmap/phase/inference-provider-extension/milestones/edge-model-group-queue-scheduling.md - Task ids:
node-simplify: Node-local provider FIFO queue가 제거되거나 Edge dispatch 이후의 실행 안전장치로 축소되어, 각 Node가 queue owner가 되지 않는다.
- Completion mode: check-on-pass
분석 결과
읽은 파일
agent-test/local/rules.mdagent-test/local/node-smoke.mdagent-test/local/edge-smoke.mdagent-ops/rules/project/domain/node/rules.mdagent-ops/rules/project/domain/testing/rules.mdapps/node/internal/node/node.goapps/node/internal/node/run_manager.goapps/node/internal/node/node_test.goapps/node/internal/node/node_concurrency_integration_test.goapps/node/internal/runtime/types.goapps/node/internal/router/router.go
테스트 환경 규칙
- test_env:
local. - 적용 profile:
node-smoke,edge-smoke. - 필수 명령:
go test -count=1 ./apps/node/internal/node. - Node 실행 요청/stream/cancel/status 경로에 닿으므로 최종 regression subtask에서 repo 내부 edge-node 진단과 full-cycle 기준을 이어서 수행한다.
테스트 커버리지 공백
- 현재 Node tests는 Node-owned FIFO queue를 성공 조건으로 삼는 테스트가 많다.
- Edge-owned queue 전환 뒤에는 Node가 queued status를 만들지 않아야 하므로 기존
TestAdmissionQueue_*계열은 삭제, 이동, 또는 "over-dispatch immediate rejection/safety" 기준으로 전환해야 한다. - Node capabilities의 queued/in_flight 값은 Edge-owned snapshot과 충돌하지 않아야 한다. queued는 0 또는 safety-only 값으로 정리해야 한다.
심볼 참조
- 제거/축소 후보:
fifoGate,admissionManager,admissionTicket,ErrConcurrencyLimitExceeded주변 queue_full/queue_timeout helper. - call site:
apps/node/internal/node/node.go:35globalGateapps/node/internal/node/node.go:36-37adapterGatesapps/node/internal/node/node.go:98-213admission enqueue/wait/launch flowapps/node/internal/node/node.go:216-242admission helperapps/node/internal/node/node.go:332-344capabilities in_flight/queued snapshotapps/node/internal/node/node_test.go:1438+admission queue testsapps/node/internal/node/node_concurrency_integration_test.go:91+queue overflow integration test
분할 판단
- shared task group:
m-edge-model-group-queue-scheduling. - 현재 subtask:
03+01_node_queue_simplify. - predecessor
01: activeagent-task/m-edge-model-group-queue-scheduling/01_edge_queue_service/complete.log없음. 구현 시작 전01_edge_queue_servicePASS complete.log가 필요하다. - snapshot/surface 조정은
02+01_surface_snapshot_contract, final regression은04+01,02,03_regression_evidence로 분리한다.
범위 결정 근거
- Node adapter provider probe, runtime adapter contracts, router lookup semantics는 바꾸지 않는다.
- Edge scheduler 구현을 이 subtask에서 재설계하지 않는다.
- 외부 OpenAI/A2A/console surface는 Node simplification 검증 범위가 아니므로 제외한다.
빌드 등급
cloud-G07: 기존 Node admission queue는 cancellation, background run, timeout, store status, provider snapshot에 걸쳐 있어 대량 테스트 전환과 concurrency risk가 크다.
구현 체크리스트
- Node
OnRunRequest에서 FIFO queue ownership을 제거하고 dispatch된 run을 즉시 실행 또는 safety reject로 처리한다. - Node capability snapshot의 queued/in-flight 의미를 Edge-owned queue와 충돌하지 않게 정리한다.
- Node admission queue tests를 삭제/전환하고 over-dispatch safety, cancel, background, store lifecycle 테스트를 남긴다.
go test -count=1 ./apps/node/internal/node가 통과한다.- CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
[REFACTOR-1] OnRunRequest Queue Ownership 제거
문제
Node가 provider FIFO queue owner다.
// apps/node/internal/node/node.go:98
98 // Admission gate (foreground and background use the same path).
110 admission := n.admissionFor(spec.Adapter, caps)
128 ticket, err := admission.enqueue()
167 if err := ticket.wait(execCtx); err != nil {
177 defer ticket.release()
해결 방법
OnRunRequest는 router resolve, store insert, runManager register, adapter execute lifecycle만 맡긴다. capacity guard가 필요하면 queue 없는 non-blocking safety gate로 두고, full이면 즉시 error event와 rejected store status를 남긴다. queued store status는 Edge queue가 소유하므로 Node-local 대기 상태로 쓰지 않는다.
수정 파일 및 체크리스트
apps/node/internal/node/node.go: admission enqueue/wait 흐름 제거 또는 safety guard로 축소.apps/node/internal/node/run_manager.go: FIFO queue helper 제거 또는 safety-only helper로 축소.
테스트 작성
- 작성:
TestOnRunRequest_DispatchedRunRunsImmediately,TestOnRunRequest_OverDispatchSafetyRejectsWithoutQueue또는 기존 테스트 전환.
중간 검증
go test -count=1 ./apps/node/internal/node -run 'TestOnRunRequest'
[REFACTOR-2] Capability Snapshot 정리
문제
Node command capabilities가 Node-local gate의 in-flight/queued를 보고한다.
// apps/node/internal/node/node.go:332
332 inFlight := 0
333 queued := 0
334 if ok {
335 inFlight = gate.activeCount()
336 queued = gate.queuedCount()
337 }
Edge-owned snapshot과 섞이면 queued 의미가 충돌한다.
해결 방법
Node는 provider availability/capacity와 safety in-flight만 보고하고 queued는 0으로 고정하거나 safety queue가 없음을 명시한다. Edge-owned queued는 02의 service snapshot이 표현한다.
수정 파일 및 체크리스트
apps/node/internal/node/node.go: capabilities result/snapshot queued semantics 정리.apps/node/internal/node/node_test.go: capabilities queued 테스트 전환.
테스트 작성
- 작성/전환:
TestOnCommandRequest_Capabilities,TestOnCommandRequest_Capabilities_InFlight, 기존TestOnCommandRequest_Capabilities_Queued삭제 또는 safety-only 이름으로 변경.
중간 검증
go test -count=1 ./apps/node/internal/node -run 'TestOnCommandRequest_Capabilities'
[REFACTOR-3] Admission Queue Test 전환
문제
apps/node/internal/node/node_test.go:1438+ 이후는 Node-owned FIFO를 전제로 한다. Edge queue 전환 뒤 이 테스트들이 그대로 남으면 목표와 반대 동작을 고정한다.
해결 방법
FIFO ordering, max_queue, queue_timeout, release promotion 테스트는 제거하거나 Edge service queue tests로 이동된 것을 확인한다. Node에는 cancel/background/store/error lifecycle과 over-dispatch immediate safety만 남긴다.
수정 파일 및 체크리스트
apps/node/internal/node/node_test.go:TestAdmissionQueue_*계열 정리.apps/node/internal/node/node_concurrency_integration_test.go: queue overflow integration test를 safety rejection 또는 제거로 전환.
테스트 작성
- 작성: over-dispatch safety event가 Edge로 도착하는 통합 테스트가 필요하면 기존
TestQueueOverflow_RejectEventObservedByEdge를 재명명해 즉시 rejection 기준으로 유지한다.
중간 검증
go test -count=1 ./apps/node/internal/node -run 'Test(AdmissionQueue|ConcurrencyLimit|QueueOverflow|OnRunRequest|OnCommandRequest_Capabilities)'
의존 관계 및 구현 순서
01_edge_queue_servicecomplete.log가 먼저 필요하다.- 구현 전 확인 후보:
- active:
agent-task/m-edge-model-group-queue-scheduling/01_edge_queue_service/complete.log - archive:
agent-task/archive/*/*/m-edge-model-group-queue-scheduling/01_edge_queue_service/complete.log
- active:
수정 파일 요약
| 파일 | 항목 |
|---|---|
apps/node/internal/node/node.go |
REFACTOR-1, REFACTOR-2 |
apps/node/internal/node/run_manager.go |
REFACTOR-1 |
apps/node/internal/node/node_test.go |
REFACTOR-1, REFACTOR-2, REFACTOR-3 |
apps/node/internal/node/node_concurrency_integration_test.go |
REFACTOR-3 |
최종 검증
go test -count=1 ./apps/node/internal/node
기대 결과: 통과. Go test cache는 허용하지 않는다.
모든 코드 변경 완료 후 반드시 CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.