blackout: enforce bounded oldest-drop queue policy on overflow (#371) #384

Merged
jihoson merged 2 commits from feature/issue-371-blackout-queue-overflow into feature/v3-session-policy-stream 2026-03-02 03:07:12 +09:00
Collaborator

Summary

  • 블랙아웃 큐 포화 시 enqueue=False로 intent를 버리던 경로를 제거하고, bounded queue의 oldest-drop 정책으로 최신 intent를 보존하도록 변경했습니다.
  • BlackoutOrderManageroverflow_drop_count를 추가해 overflow eviction을 명시적으로 추적합니다.
  • _maybe_queue_order_intent()에서 overflow 발생 시 "oldest intent evicted" 로그를 남기고, 큐 비활성(max_queue_size<=0)인 경우만 fail-stop 로그를 남깁니다.
  • 포화 회귀 테스트를 추가해 oldest가 제거되고 최신 intent가 복구 배치에 남는 동작을 검증했습니다.
  • 요구사항 문구를 정책과 정합화했습니다(REQ-V3-004: bounded queue + oldest-drop).

Scope Mapping

  • REQ: REQ-V3-004
  • TASK: TASK-CODE-008
  • TEST: TEST-ACC-017

Validation

  • ruff check src/core/blackout_manager.py src/main.py tests/test_blackout_manager.py tests/test_main.py
  • pytest -q tests/test_blackout_manager.py
  • pytest -q tests/test_main.py -k "blackout_queue_overflow_keeps_latest_intent or blackout_queues_order_and_skips_submission or process_blackout_recovery"
  • python3 scripts/validate_ouroboros_docs.py
  • python3 scripts/validate_governance_assets.py origin/feature/v3-session-policy-stream...HEAD
  • python3 scripts/validate_docs_sync.py
## Summary - 블랙아웃 큐 포화 시 `enqueue=False`로 intent를 버리던 경로를 제거하고, bounded queue의 `oldest-drop` 정책으로 최신 intent를 보존하도록 변경했습니다. - `BlackoutOrderManager`에 `overflow_drop_count`를 추가해 overflow eviction을 명시적으로 추적합니다. - `_maybe_queue_order_intent()`에서 overflow 발생 시 "oldest intent evicted" 로그를 남기고, 큐 비활성(`max_queue_size<=0`)인 경우만 fail-stop 로그를 남깁니다. - 포화 회귀 테스트를 추가해 oldest가 제거되고 최신 intent가 복구 배치에 남는 동작을 검증했습니다. - 요구사항 문구를 정책과 정합화했습니다(REQ-V3-004: bounded queue + oldest-drop). ## Scope Mapping - REQ: `REQ-V3-004` - TASK: `TASK-CODE-008` - TEST: `TEST-ACC-017` ## Validation - `ruff check src/core/blackout_manager.py src/main.py tests/test_blackout_manager.py tests/test_main.py` - `pytest -q tests/test_blackout_manager.py` - `pytest -q tests/test_main.py -k "blackout_queue_overflow_keeps_latest_intent or blackout_queues_order_and_skips_submission or process_blackout_recovery"` - `python3 scripts/validate_ouroboros_docs.py` - `python3 scripts/validate_governance_assets.py origin/feature/v3-session-policy-stream...HEAD` - `python3 scripts/validate_docs_sync.py`
agentson added 1 commit 2026-03-02 02:57:20 +09:00
blackout: enforce bounded oldest-drop queue policy on overflow (#371)
All checks were successful
Gitea CI / test (push) Successful in 33s
Gitea CI / test (pull_request) Successful in 33s
7959b749c7
Author
Collaborator

PR 리뷰 (Claude Code)

전체 판정: LGTM

CI 통과, 167개 테스트 전체 통과 확인.


로직 검증

enqueue() 정책 분기

조건 기존 동작 변경 후 동작
max_queue_size <= 0 0 >= 0 → return False 명시적 return False
포화 (len >= max) return False (유실) popleft + append → return True (oldest 제거, latest 보존)
여유 있음 append + return True 동일

의미 변화: 큐 비활성과 포화가 명확히 분리되었고, 포화 시 intent 유실이 제거되었습니다.

overflow 감지 방식

enqueue 전후로 overflow_drop_count를 비교해 overflow 발생을 감지하는 방식이 올바릅니다. enqueue()가 기존 인터페이스(bool 반환)를 유지하면서 overflow 여부를 알 수 있는 유일한 방법입니다.

테스트 경계값 검증

  • max_queue_size=2, 3개 enqueue → ["000002", "000003"]만 복구 배치에 포함
  • max_queue_size=1, 2개 enqueue → 최신 "000660"만 복구 배치에 포함

소견

_coerce_nonnegative_int + getattr 조합이 과방어적

overflow_drop_countint 타입의 프로퍼티로 타입 보장이 되어 있으므로:

# 현재
before = _coerce_nonnegative_int(getattr(BLACKOUT_ORDER_MANAGER, "overflow_drop_count", 0))

# 충분함
before = BLACKOUT_ORDER_MANAGER.overflow_drop_count

블로킹 사항은 아닙니다.

## PR 리뷰 (Claude Code) ### 전체 판정: ✅ LGTM CI 통과, 167개 테스트 전체 통과 확인. --- ### 로직 검증 **`enqueue()` 정책 분기** | 조건 | 기존 동작 | 변경 후 동작 | |------|----------|-------------| | `max_queue_size <= 0` | `0 >= 0` → return False | 명시적 return False | | 포화 (`len >= max`) | return False (유실) | popleft + append → return True (oldest 제거, latest 보존) | | 여유 있음 | append + return True | 동일 | 의미 변화: 큐 비활성과 포화가 명확히 분리되었고, 포화 시 intent 유실이 제거되었습니다. **overflow 감지 방식** enqueue 전후로 `overflow_drop_count`를 비교해 overflow 발생을 감지하는 방식이 올바릅니다. `enqueue()`가 기존 인터페이스(`bool` 반환)를 유지하면서 overflow 여부를 알 수 있는 유일한 방법입니다. **테스트 경계값 검증** - `max_queue_size=2`, 3개 enqueue → `["000002", "000003"]`만 복구 배치에 포함 ✅ - `max_queue_size=1`, 2개 enqueue → 최신 `"000660"`만 복구 배치에 포함 ✅ --- ### 소견 **`_coerce_nonnegative_int` + `getattr` 조합이 과방어적** `overflow_drop_count`는 `int` 타입의 프로퍼티로 타입 보장이 되어 있으므로: ```python # 현재 before = _coerce_nonnegative_int(getattr(BLACKOUT_ORDER_MANAGER, "overflow_drop_count", 0)) # 충분함 before = BLACKOUT_ORDER_MANAGER.overflow_drop_count ``` 블로킹 사항은 아닙니다.
agentson added 1 commit 2026-03-02 03:03:36 +09:00
test: align blackout queue mocks with overflow counter contract
All checks were successful
Gitea CI / test (push) Successful in 32s
Gitea CI / test (pull_request) Successful in 32s
96e5de7c5d
Author
Collaborator

추가 리뷰 (Claude Code)

이전 소견 반영 현황

항목 상태
_coerce_nonnegative_int + getattr 제거 → 직접 접근 반영

판정: LGTM

직접 접근으로 바뀌면서 기존 mock에 overflow_drop_count 속성이 없으면 AttributeError가 발생하는 문제를 test_blackout_queues_order_and_skips_submission mock에 overflow_drop_count = 0을 추가해 정확히 대응했습니다. 167개 테스트 전체 재통과 확인.

## 추가 리뷰 (Claude Code) ### 이전 소견 반영 현황 | 항목 | 상태 | |------|------| | `_coerce_nonnegative_int` + `getattr` 제거 → 직접 접근 | ✅ 반영 | ### 판정: ✅ LGTM 직접 접근으로 바뀌면서 기존 mock에 `overflow_drop_count` 속성이 없으면 `AttributeError`가 발생하는 문제를 `test_blackout_queues_order_and_skips_submission` mock에 `overflow_drop_count = 0`을 추가해 정확히 대응했습니다. 167개 테스트 전체 재통과 확인.
jihoson merged commit ccceb38483 into feature/v3-session-policy-stream 2026-03-02 03:07:12 +09:00
jihoson deleted branch feature/issue-371-blackout-queue-overflow 2026-03-02 03:07:12 +09:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jihoson/The-Ouroboros#384