o2o-site-AEO/solution/backend/services
hbyang 4650125c6c [fix] solution/backend: 미니블로그 자동 게재가 양쪽 끝에서 끊겨 있었다 — 생성 미등록·승인 후 발행 사망
증상은 둘 다 "메일이 안 온다" / "승인했는데 홈페이지가 그대로" 로만 보인다. 서버는 정상으로
뜨고 로그에도 에러가 없어서 눈으로 원인을 못 찾는 종류다.

① 재고 채우기가 스케줄러에 **등록돼 있지 않았다.** `scheduler/jobs.py` 에 함수는 있고
   `__init__.py` 주석도 "새벽에 재고를 채운다" 라고 말하는데 add_job 한 줄이 없어 한 번도
   돈 적이 없다. 09:00 발송만 돌고 보낼 글은 0건이었다 — 지금 DB 의 254건은 전부 화면의
   [지금 생성하기] 로 손으로 만든 것이다.
   → 04:10 KST 등록(발송보다 앞서야 그날 아침에 나갈 재고가 있다)

② 승인 뒤 재발행이 죽는다. `post_service._enqueue_build` 가 requested_by 에
   "blog-approval" 이라는 **라벨**을 넣었고 `build_service._log` 가 그걸 uuid.UUID() 에
   넣다 ValueError 를 던졌다. 하필 _log 는 사이트를 다 구운 **뒤**, sites.status 를
   PUBLISHED 로 찍기 **전**에 불린다 — 굽기는 끝났는데 발행만 안 된 채 3회 재시도 후 DEAD.
   실측: BUILD 잡 5건(2026-09-23~09-30)이 전부 이 원인이고 전부 미니블로그 승인분이었다.
   → 호출부는 사장님 ID 를 넣고, 파서(_actor_uuid)는 모양이 틀리면 기록만 비우고 진행한다.
     감사 기록 한 줄이 발행을 막는 것은 순서가 뒤집힌 것이다. rollback_service 도 같은 파서.

- scheduler/__init__: blog-drafts 등록 + 왜 빠져 있었는지
- services/build_service: _actor_uuid 신설, _log 가 그것만 쓴다
- services/post_service: requested_by = str(owner_user_id)
- services/rollback_service: 같은 파서 재사용

테스트 7건 추가(build 4 · scheduler 3), 전부 통과.
test_build_publish.py 의 기존 실패 13건은 변동 없음 — 원본으로 되돌려 측정해 확인했다
(원본 13 failed/2 passed, 변경 후 13 failed/6 passed). 그 13건은 컨테이너 테스트 DB
쪽 문제다(로그: lease 갱신 실패 InvalidCatalogNameError) — 이 변경과 무관하고 미해결로 남긴다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-30 17:31:10 +09:00
..
agent [feat] solution/backend: 카카오 로그인 — 회원번호로 카톡 채널을 코드 없이 잇는다 2026-09-30 16:27:54 +09:00
collector [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
external [feat] solution,deploy: 카카오 로그인을 인가 코드 교환으로 — 시크릿을 서버에 가둔다 2026-09-30 16:51:05 +09:00
grounding [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
llm [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
prompts [feat] solution/backend: SNS 캡션 첫 문장에 지역·업종·상호 2026-09-30 15:43:49 +09:00
resources [feat] solution,postgres-init,docs: SNS 게재 — 사장님이 누르면 쓰고, 승인받아, 사장님 계정으로 올린다 2026-09-14 15:46:44 +09:00
activity_feed.py [feat] solution/site,shared: 새 템플릿 8종을 카페·음식점·병원에도 연다 — 객실 문구를 업종별로 2026-09-30 14:57:02 +09:00
alert_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
auth_service.py [feat] solution,deploy: 카카오 로그인을 인가 코드 교환으로 — 시크릿을 서버에 가둔다 2026-09-30 16:51:05 +09:00
azure_static.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
blog_jobs.py [feat] solution/backend: 승인 알림을 카톡으로도 발송하고 웹훅이 메시지를 그린다 (Event API 2-1) 2026-09-29 16:13:07 +09:00
blog_service.py merge: origin/main(에이전트 여러 동작 · 사진 도구 · 카톡 승인 알림) 을 feature/template-catalog 에 병합 2026-09-30 13:51:53 +09:00
booking_request_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
build_service.py [fix] solution/backend: 미니블로그 자동 게재가 양쪽 끝에서 끊겨 있었다 — 생성 미등록·승인 후 발행 사망 2026-09-30 17:31:10 +09:00
collect_service.py [fix] solution/backend: Teams 는 장애만 — 수집·발행 시작·완료 알림 제거, 빌드 실패 중복 발송 정리 2026-09-30 16:37:24 +09:00
copy_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
copy_steps.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
fact_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
faq_fill.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
faq_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
indexnow.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
intro_summary.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
itinerary_llm_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
itinerary.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
job_progress.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
job_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
kakao_link_service.py [feat] solution/backend: 카카오 로그인 — 회원번호로 카톡 채널을 코드 없이 잇는다 2026-09-30 16:27:54 +09:00
local_content_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
local_restaurant_enrichment.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
mail_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
media_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
notify_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
ops_service.py [feat] solution/backend,frontend: 관리자가 모든 사업장을 열고 관리 — 사이트관리 검색·업종 필터·삭제, 사장님 더보기 정리 2026-09-30 15:34:20 +09:00
place_category.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
place_research.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
place_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
post_service.py [fix] solution/backend: 미니블로그 자동 게재가 양쪽 끝에서 끊겨 있었다 — 생성 미등록·승인 후 발행 사망 2026-09-30 17:31:10 +09:00
publish_gate.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
render_report.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
render_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
review_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
rollback_service.py [fix] solution/backend: 미니블로그 자동 게재가 양쪽 끝에서 끊겨 있었다 — 생성 미등록·승인 후 발행 사망 2026-09-30 17:31:10 +09:00
search_console_alerts.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
search_console_client.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
search_console_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
search_console_settings.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
seo_audit.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
seo_keywords.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
showcase_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
site_payload.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
site_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
site_slug.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
site_thumbnail.py [feat] solution/backend: 발행·재발행마다 사이트 화면을 찍어 썸네일로 — 실패하면 대표 사진 2026-09-30 15:34:21 +09:00
snapshot.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
social_account_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
social_service.py [feat] solution/backend: SNS 캡션 첫 문장에 지역·업종·상호 2026-09-30 15:43:49 +09:00
song_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
stay_guide.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
story_service.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
teams_webhook.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00
vision_service.py [fix] solution/backend: Teams 는 장애만 — 수집·발행 시작·완료 알림 제거, 빌드 실패 중복 발송 정리 2026-09-30 16:37:24 +09:00
weather_notes.json [fix] site,solution/backend: 날씨 상태 라벨을 코드별 고유값으로 — 구간 뭉치기 제거 2026-09-22 08:36:09 +09:00
weather_notes.py [chore] solution,admin,ontology: 코드 주석을 한 줄로 — 히스토리 주석 삭제 2026-09-28 16:05:19 +09:00