AtCoder-NoviSteps / AtCoderNoviSteps

【非公式】 AtCoder 上の問題について、取組み状況を記録していくサイトです。各問題が細かく難易度付けされており、必要な知識を段階的に習得できます。
https://atcoder-novisteps.vercel.app/
MIT License
36 stars 8 forks source link

外部APIへのアクセスに関する汎用的な処理(リトライ・レートリミット)を導入しましょう #1523

Open KATO-Hiro opened 5 days ago

KATO-Hiro commented 5 days ago
private async withRetry<T>(
  operation: () => Promise<T>,
  retries = 3,
  delay = 1000
): Promise<T> {
  try {
    return await operation();
  } catch (error) {
    if (retries > 0) {
      await new Promise(resolve => setTimeout(resolve, delay));
      return this.withRetry(operation, retries - 1, delay * 2);
    }
    throw error;
  }
}
class RateLimiter {
  private queue: Array<() => Promise<void>> = [];
  private processing = false;

  constructor(private rateLimit: number, private interval: number) {}

  async schedule<T>(task: () => Promise<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      this.queue.push(async () => {
        try {
          resolve(await task());
        } catch (error) {
          reject(error);
        }
      });
      this.process();
    });
  }

  private async process(): Promise<void> {
    if (this.processing) return;
    this.processing = true;

    while (this.queue.length > 0) {
      const batch = this.queue.splice(0, this.rateLimit);
      await Promise.all(batch.map(task => task()));
      await new Promise(resolve => setTimeout(resolve, this.interval));
    }

    this.processing = false;
  }
}