AtCoderNoviSteps icon indicating copy to clipboard operation
AtCoderNoviSteps copied to clipboard

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

Open KATO-Hiro opened this issue 1 year ago • 0 comments

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;
  }
}

KATO-Hiro avatar Nov 23 '24 12:11 KATO-Hiro