ops(pipeline): embed/chunk 고속 컨슈머 분리 + 배치 1→10 — LLM 사이클 인질 해소
진단(2026-06-12 용량 평가): 단일 루프에서 classify(~190s×3)가 사이클을 점유, 건당 <1s 인 embed/chunk 가 사이클당 1건 캡 → 실효 ~580/일 vs 수요 최대 2,700/일, 적체 3,570 + 신규 문서 벡터 미적재(RAG 검색 누락). 4070 가동률 0% = 순수 구조 캡. 수리 = markdown 분리(05-01) 선례: consume_fast_queue 1분 잡 + 배치 10(GPU 공유 보수값, 캡 ~14,400/일). 세 컨슈머 stage 집합 disjoint(stale reset 이중 복구 방지). retrieval 로직·임베딩 모델 무접촉. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -23,7 +23,11 @@ def _fake_consumer_env(monkeypatch, held):
|
||||
monkeypatch.setattr(queue_consumer, "reset_stale_items", fake_reset)
|
||||
monkeypatch.setattr(
|
||||
queue_consumer, "_load_workers",
|
||||
lambda: {s: object() for s in queue_consumer.MAIN_QUEUE_STAGES + ["markdown"]},
|
||||
lambda: {
|
||||
s: object()
|
||||
for s in (queue_consumer.MAIN_QUEUE_STAGES
|
||||
+ queue_consumer.FAST_QUEUE_STAGES + ["markdown"])
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(queue_consumer, "_hold_logged", False)
|
||||
monkeypatch.setattr(settings, "pipeline_held_stages", held)
|
||||
@@ -46,8 +50,8 @@ async def test_consume_queue_skips_held_stages(monkeypatch):
|
||||
assert "classify" not in processed
|
||||
assert "summarize" not in processed
|
||||
assert "deep_summary" not in processed
|
||||
# GPU/특화 스테이지는 계속 처리
|
||||
for stage in ("extract", "embed", "chunk", "stt", "fulltext"):
|
||||
# 특화 스테이지는 계속 처리 (embed/chunk 는 2026-06-12 fast 컨슈머로 분리)
|
||||
for stage in ("extract", "stt", "fulltext"):
|
||||
assert stage in processed
|
||||
|
||||
|
||||
@@ -60,6 +64,36 @@ async def test_consume_queue_empty_hold_processes_all(monkeypatch):
|
||||
assert processed == list(queue_consumer.MAIN_QUEUE_STAGES)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fast_consumer_processes_embed_chunk_only(monkeypatch):
|
||||
"""fast 컨슈머(2026-06-12 분리) = embed/chunk 전용, LLM 사이클과 디커플."""
|
||||
processed = _fake_consumer_env(monkeypatch, [])
|
||||
|
||||
await queue_consumer.consume_fast_queue()
|
||||
|
||||
assert processed == ["embed", "chunk"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fast_consumer_respects_hold(monkeypatch):
|
||||
processed = _fake_consumer_env(monkeypatch, ["embed"])
|
||||
|
||||
await queue_consumer.consume_fast_queue()
|
||||
|
||||
assert processed == ["chunk"]
|
||||
|
||||
|
||||
def test_fast_split_invariants():
|
||||
"""세 컨슈머 stage 집합 disjoint + embed/chunk 배치 상향 회귀 가드."""
|
||||
main = set(queue_consumer.MAIN_QUEUE_STAGES)
|
||||
fast = set(queue_consumer.FAST_QUEUE_STAGES)
|
||||
md = set(queue_consumer.MARKDOWN_QUEUE_STAGES)
|
||||
assert not (main & fast) and not (main & md) and not (fast & md)
|
||||
assert fast == {"embed", "chunk"}
|
||||
assert queue_consumer.BATCH_SIZE["embed"] >= 10
|
||||
assert queue_consumer.BATCH_SIZE["chunk"] >= 10
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_markdown_consumer_not_held(monkeypatch):
|
||||
"""markdown 컨슈머는 홀드 비대상 (LLM 무관 — marker GPU 변환)."""
|
||||
|
||||
Reference in New Issue
Block a user