쿠폰 발급 FLOW Chart - Hot-stock/backend GitHub Wiki

🎟️ 이벤트 참여 프로세스

시나리오

사용자는 특정 이벤트에 참여를 요청하고, 참여 결과를 실시간으로 확인하며, 쿠폰 발급 상태를 추적할 수 있습니다. 이 과정은 아래 7단계로 구성됩니다.

  1. 이벤트 참여 요청: 사용자가 POST /tickets/{eventId} API를 호출하여 특정 이벤트에 참여 요청을 보냅니다.
  2. 참여 데이터 저장: 서버는 Redis에 참여자의 정보를 저장하고, 참여자의 순번을 계산합니다. 중복 참여 시 예외를 반환합니다.
  3. 참여 결과 반환: 서버는 사용자에게 참여 결과를 JSON 응답으로 반환하며, 여기에는 사용자 순번 등이 포함됩니다.
  4. 쿠폰 발급 상태 실시간 확인: 사용자는 GET /tickets/result API를 통해 SSE 방식으로 쿠폰 발급 상태를 실시간으로 확인할 수 있습니다.
  5. 비동기 스케줄러 실행: 서버의 스케줄러가 10초마다 실행되어 Redis 큐의 대기 중인 참여자 데이터를 처리합니다.
  6. 유효한 참여자 검증 및 쿠폰 생성: 큐에 데이터가 있으면 유효한 참여자를 검증하고 이벤트 상태를 업데이트하며, 쿠폰을 생성합니다.
  7. 쿠폰 발급 성공 메시지 전송: Kafka를 통해 쿠폰 발급 성공 메시지를 사용자에게 전송하고, Redis에서 해당 참여자 데이터를 삭제합니다.

프로세스


프로세스 다이어그램

sequenceDiagram
    participant Client as Client
    participant Server as Server
    participant Redis as Redis
    participant Kafka as Kafka
    Client->>Server: POST /tickets/{eventId} (participateOfEvent)
    Server->>Redis: addParticipation (Queue, Participant Set)
    Redis-->>Server: Return Turn
    
    Server->>Client: Return Participation Turn
    
    loop Every 10 seconds (Scheduler)
        Server->>Redis: Get Key from Redis Queue
        alt If Key is found
            Server->>Redis: Extract Participation Data
            Redis-->>Server: Return Participation Data
            
            Server->>Server: validateEventParticipant (eventId, participations)
            Server->>Server: updateEventStatus (eventId, participations, key)
            alt If excess coupons exist
                Server->>Server: calculateValidCouponParticipants
                Server->>Server: bulkGenerateCoupon (eventId, validParticipants)
                Server->>Kafka: sendCouponMessage (Coupon Issued)
            else If no excess coupons
                Server-->>Server: End Process
            end
            Server->>Redis: removeParticipation (Queue Key)
        else No Matching Key Found
            Server-->>Server: End Cron Job
        end
    end
    
    Client->>Server: GET /tickets/result (getResultOfCoupon)
    Server-->>Client: SSE: Coupon Results

에러 처리 및 예외 상황

예외 처리 흐름

테스트 케이스

1. 비로그인 유저 호출 테스트

  • 목적: 로그인하지 않은 사용자가 API를 호출할 때, 요청자의 IP 주소를 기반으로 호출 제한이 적용되는지 확인.
  • Given: 사용자가 로그인하지 않고, API 호출을 시도합니다.
  • When: API 호출 시 요청자의 IP 주소를 획득하고, Redis에 저장한 후, 호출 제한을 적용합니다.
  • Then: 호출 제한 버킷이 생성되고, API 호출이 정상적으로 제한자가 작동하는지 확인합니다.

2. 로그인 유저 호출 테스트

  • 목적: 로그인된 사용자가 Access Token을 이용해 API를 호출할 때, 호출 제한이 정상적으로 동작하는지 확인.
  • Given: 사용자가 로그인한 상태에서 API 호출을 시도합니다.
  • When: Access Token을 기반으로 사용자 식별을 하고, Redis에 해당 사용자와 연관된 호출 제한 버킷을 조회합니다.
  • Then: 호출 제한이 정상적으로 적용되고, 사용자가 설정된 제한 내에서 API 호출을 성공할 수 있는지 확인합니다.

3. 토큰 리필 테스트

  • 목적: 사용자의 호출 제한 버킷에 있는 토큰이 리필되는지 확인.
  • Given: 사용자의 API 호출 제한이 다 소모된 상태입니다.
  • When: 일정 시간이 경과하여 호출 제한 토큰이 자동으로 리필됩니다.
  • Then: 사용자의 토큰이 다시 채워지고, API 호출이 정상적으로 허용되는지 확인합니다.

4. 호출 제한 초과 테스트

  • 목적: 사용자가 설정된 호출 횟수를 초과했을 때, 호출이 차단되는지 확인.
  • Given: 사용자가 정해진 호출 횟수를 초과한 상태입니다.
  • When: 사용자가 추가로 API 호출을 시도합니다.
  • Then: **HTTP 상태 코드 429 (Too Many Requests)**와 함께 호출이 차단됩니다.

5. 호출 제한 초기화 테스트

  • 목적: 호출 제한 기간이 만료된 후, 새로운 API 호출이 허용되는지 확인.
  • Given: 사용자가 호출 제한에 도달했으나, 제한 시간이 경과했습니다.
  • When: 제한 시간 후 API를 호출합니다.
  • Then: 호출 제한이 리셋되고, 새로운 호출이 허용되는지 확인합니다.