Woozy_DevLog
article thumbnail

전적 검색 / 갱신 로직

현재 소환사 전적 검색 / 갱신은 여러 riot api를 통해 값을 가져온다.

  1. 소환사 이름으로 소환사의 개인 정보(summonerId, puuid,…)를 가져온다.
  2. 소환사의 summonerId로 소환사의 전적(win, tier, level, lp…)을 가져온다.
  3. 소환사의 summmonerId로 소환사의 모스트 챔피언을 가져온다.
  4. 소환사의 puuid로 플레이한 경기의 id인 matchId 10개를 가져온다.
  5. 소환사의 matchId로 게임 내 상세 데이터를 가져온다.

여기서 4번이 10개를 가져오면 반복문을 통해 게임내 데이터를 가져온다.

그러므로 소환사 검색 / 갱신은 riot api에 요청하는 양은 14번 정도이다.

그리고 riot에서는 api 요청 제한이 걸려있고 한번 제한이 걸리면 1 , 2분간 riot api를 사용하지 못하게 된다.

그래서 한번 소환사 전적 갱신한 소환사에 대해서는 약 5분의 텀을 두어 과도한 api 요청을 막는게 목적이다.

해결

NestJs 에서는 인터셉터를 통해 http 요청의 처리를 컨트롤러가 실행 전/ 실행 후에 요청 값을 수정 할 수 있다.

그래서 전적갱신의 요청 파라미터 값을 인터셉터에서 먼저 필터링 하는 로직을 구현하였다.

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class ThrottleInterceptor implements NestInterceptor {
  private readonly cache = new Map<string, number>();

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const summonerName = request.params.summonerName;
    const requestTime = Date.now();

    if (this.cache.has(summonerName)) {
      const lastRequestTime = this.cache.get(summonerName);

      if (requestTime - lastRequestTime < 5 * 60 * 1000) {
        throw new HttpException('Too many requests', HttpStatus.TOO_MANY_REQUESTS);
      }
    }

    this.cache.set(summonerName, requestTime);

    return next.handle();
  }
}

인터셉터의 필드를 Map 자료구조로 키(소환사 이름) , 값(요청 시간)으로 지정하였다.

그리고 요청이 오면 해당 필드에서 소환사를 찾고 요청 시간이 5분 미만이면 429에러를 뱉는다.

테스트

it("/GET 소환사 전적 갱신 특정 소환사 갱신 후 해당 소환사 5분 안에 다시 요청시 error?", async () => {
  const summonerName = encodeURIComponent("쿠바버샷추가");
  await request(app.getHttpServer()).get(`/summoner/refresh/${summonerName}`);
  const response = await request(app.getHttpServer()).get(
    `/summoner/refresh/${summonerName}`
  );

  expect(response.statusCode).toBe(429);
  expect(response.body.message).toEqual("Too many requests");
});

같은 소환사를 2번 전적 갱신을 할 경우 정상적으로 429 코드와 에러메세지가 발생한다.

e2e테스트를 통해 확실하게 api를 검증 할 수 있다.

profile

Woozy_DevLog

@Woozy_Dev

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!