다크 모드
아키텍처
trigger-dispatcher 개요
trigger-dispatcher는 EventBridge Scheduler → Core API → SQS 파이프라인을 수행하는 단일 Lambda 함수입니다. 트리거 타입별로 서로 다른 SQS 큐에 메시지를 라우팅하여, 각 소비자 서비스가 독립적으로 이벤트를 처리할 수 있게 합니다.
이벤트 처리 흐름
정보
EventBridge Scheduler는 Lambda를 비동기(async) 호출합니다. Lambda 실패 시 최대 2회 자동 재시도됩니다.
입력 이벤트
EventBridge Scheduler가 Lambda에 전달하는 payload:
json
{
"trigger_eid": "string (EID)",
"trigger_type": "string (트리거 타입)"
}트리거 타입 라우팅 테이블
Lambda는 trigger_type에 따라 메시지를 전송할 SQS 큐를 결정합니다.
| 트리거 타입 | 대상 큐 | 소비자 | 설명 |
|---|---|---|---|
loop.confirmed.day_before | SQS_ASSISTANT_QUEUE_URL | truloop-assistant | 확정된 룹 전날 알림 |
loop.confirmed.morning_of | SQS_ASSISTANT_QUEUE_URL | truloop-assistant | 확정된 룹 당일 아침 알림 |
주의
알 수 없는 trigger_type이 들어오면 ValueError를 발생시켜 Lambda를 실패 처리합니다. 새 트리거 타입 추가 시 TRIGGER_TYPE_ROUTES 딕셔너리에 등록이 필요합니다.
Phase 2 계획 (코드 주석 기반)
향후 truloop-core가 직접 처리하는 트리거 타입이 추가될 예정입니다. Core 전용 SQS 큐(SQS_CORE_QUEUE_URL)로 라우팅하는 형태가 될 것입니다.
python
# Phase 2: Core가 처리하는 타입은 Core 큐로
# "loop.status.reminder": os.environ["SQS_CORE_QUEUE_URL"],Core API 연동
Lambda는 truloop-core의 Internal API를 호출합니다. 인증은 Bearer API Key 방식입니다.
호출 엔드포인트
| Method | Path | 설명 |
|---|---|---|
GET | /triggers/{trigger_eid}/targets | 트리거 대상 사용자 그룹 조회 (페이지네이션) |
POST | /triggers/{trigger_eid}/complete | 트리거 디스패치 완료 통보 |
페이지네이션
대상 조회 API는 커서 기반 페이지네이션을 사용합니다.
| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
size | integer | 50 | 페이지당 그룹 수 |
cursor | string | - | 다음 페이지 커서 |
응답 구조:
json
{
"target_groups": [
{
"context": { },
"user_eids": ["user_eid_1", "user_eid_2"]
}
],
"has_next": true,
"next_cursor": "string"
}SQS 메시지 포맷
각 target_group이 하나의 SQS 메시지로 변환됩니다.
json
{
"event_id": "{trigger_eid}:{cursor}:{group_index}",
"trigger_eid": "string",
"trigger_type": "loop.confirmed.day_before",
"context": { },
"target_user_eids": ["user_eid_1", "user_eid_2"]
}event_id는 {trigger_eid}:{cursor}:{group_index} 형태로 구성되어 메시지를 고유하게 식별합니다.
에러 처리
| 상황 | 동작 | 결과 |
|---|---|---|
| Core API 404 (트리거 삭제됨) | 로그 후 정상 반환 | {status: "skipped", reason: "deleted"} |
| Core API 기타 HTTP 에러 | 예외 전파 | Lambda 실패 → 비동기 재시도 (최대 2회) |
| 네트워크/타임아웃 에러 | 예외 전파 | Lambda 실패 → 비동기 재시도 (최대 2회) |
| 알 수 없는 trigger_type | ValueError 발생 | Lambda 실패 → 비동기 재시도 (최대 2회) |
정보
Core API 호출 타임아웃은 30초입니다. Lambda 전체 타임아웃은 **300초(5분)**로, 대량 페이지네이션에도 충분한 여유가 있습니다.
핸들러 코드
python
def handler(event, context):
"""EventBridge Schedule이 직접 호출. event = TriggerScheduleInput."""
trigger_eid = event["trigger_eid"]
trigger_type = event["trigger_type"]
queue_url = TRIGGER_TYPE_ROUTES.get(trigger_type)
if not queue_url:
raise ValueError(f"Unknown trigger type: {trigger_type}")
cursor = None
group_index = 0
try:
while True:
params = {"size": "50"}
if cursor:
params["cursor"] = cursor
result = _core_get(f"/triggers/{trigger_eid}/targets", params)
for group in result["target_groups"]:
event_id = f"{trigger_eid}:{cursor or 'start'}:{group_index}"
sqs.send_message(
QueueUrl=queue_url,
MessageBody=json.dumps({
"event_id": event_id,
"trigger_eid": trigger_eid,
"trigger_type": trigger_type,
"context": group["context"],
"target_user_eids": group["user_eids"],
}),
)
group_index += 1
if not result["has_next"]:
break
cursor = result["next_cursor"]
_core_post(f"/triggers/{trigger_eid}/complete")
except HTTPError as e:
if e.code == 404:
return {"status": "skipped", "reason": "deleted"}
raise
return {"status": "dispatched", "messages_sent": group_index}변경 이력
| 날짜 | 내용 |
|---|---|
| 2026-03-11 | 최초 작성 — trigger-dispatcher 아키텍처 문서 |