fix(agent-office/blog): generate/market/review 비동기 task 폴링 추가
blog-lab의 generate/market/review 엔드포인트는 task_id만 즉시 반환하고 BackgroundTask로 실제 작업을 수행한다. 기존 코드는 응답에서 바로 post_id를 꺼내려 해 항상 'generate did not return post_id' 실패. 공통 폴링 헬퍼 _await_task로 research처럼 status=succeeded 대기하도록 수정. 점수는 review 완료 후 post를 다시 읽어 review_score로 판정. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -49,49 +49,50 @@ class BlogAgent(BaseAgent):
|
||||
await self.transition("working", f"리서치: {keyword}", task_id)
|
||||
asyncio.create_task(self._run_pipeline(task_id, keyword))
|
||||
|
||||
async def _await_task(self, step: str, task_id: str, timeout_sec: int = 240) -> Optional[int]:
|
||||
"""blog-lab BackgroundTask 완료 폴링. 완료 시 result_id 반환."""
|
||||
attempts = max(1, timeout_sec // 5)
|
||||
for _ in range(attempts):
|
||||
await asyncio.sleep(5)
|
||||
status = await service_proxy.blog_task_status(task_id)
|
||||
s = status.get("status")
|
||||
if s == "succeeded":
|
||||
return status.get("result_id")
|
||||
if s == "failed":
|
||||
raise Exception(f"{step} failed: {status.get('error')}")
|
||||
raise Exception(f"{step} timeout ({timeout_sec}s 내 완료되지 않음)")
|
||||
|
||||
async def _run_pipeline(self, task_id: str, keyword: str) -> None:
|
||||
try:
|
||||
# 1) 리서치 시작 (백그라운드 task)
|
||||
# 1) 리서치
|
||||
research = await service_proxy.blog_research(keyword)
|
||||
research_task_id = research.get("task_id")
|
||||
keyword_id = None
|
||||
|
||||
# 2) 리서치 완료까지 폴링 (최대 3분)
|
||||
timed_out = True
|
||||
for _ in range(36):
|
||||
await asyncio.sleep(5)
|
||||
status = await service_proxy.blog_task_status(research_task_id)
|
||||
if status.get("status") == "succeeded":
|
||||
keyword_id = status.get("result_id")
|
||||
timed_out = False
|
||||
break
|
||||
if status.get("status") == "failed":
|
||||
raise Exception(f"research failed: {status.get('error')}")
|
||||
if timed_out:
|
||||
raise Exception("research timeout (3분 내 완료되지 않음)")
|
||||
keyword_id = await self._await_task("research", research.get("task_id"), 180)
|
||||
if not keyword_id:
|
||||
raise Exception("research succeeded but result_id missing")
|
||||
|
||||
# 3) 작가 단계
|
||||
# 2) 작가 단계 (비동기)
|
||||
await self.transition("working", f"글 생성: {keyword}", task_id)
|
||||
gen = await service_proxy.blog_generate(keyword_id)
|
||||
post_id = gen.get("post_id") or gen.get("id")
|
||||
post_id = await self._await_task("generate", gen.get("task_id"), 300)
|
||||
if not post_id:
|
||||
raise Exception("generate did not return post_id")
|
||||
raise Exception("generate succeeded but post_id missing")
|
||||
|
||||
# 4) 마케터 단계
|
||||
# 3) 마케터 단계 (비동기)
|
||||
await self.transition("working", "링크 삽입 중", task_id)
|
||||
await service_proxy.blog_market(post_id)
|
||||
mkt = await service_proxy.blog_market(post_id)
|
||||
await self._await_task("market", mkt.get("task_id"), 180)
|
||||
|
||||
# 5) 평가자 단계
|
||||
# 4) 평가자 단계 (비동기)
|
||||
await self.transition("working", "품질 리뷰 중", task_id)
|
||||
review = await service_proxy.blog_review(post_id)
|
||||
score = review.get("score")
|
||||
passed = review.get("passed", False)
|
||||
rev = await service_proxy.blog_review(post_id)
|
||||
await self._await_task("review", rev.get("task_id"), 180)
|
||||
|
||||
post = await service_proxy.blog_get_post(post_id)
|
||||
title = post.get("title", "(제목 없음)")
|
||||
excerpt = (post.get("body") or "")[:300]
|
||||
post_after = await service_proxy.blog_get_post(post_id)
|
||||
score = post_after.get("review_score")
|
||||
passed = (score or 0) >= 42
|
||||
|
||||
title = post_after.get("title", "(제목 없음)")
|
||||
excerpt = (post_after.get("body") or "")[:300]
|
||||
|
||||
update_task_status(task_id, "pending", {
|
||||
"keyword": keyword,
|
||||
|
||||
Reference in New Issue
Block a user