From 3104a54fe729972986eb79ca1716143730ef4006 Mon Sep 17 00:00:00 2001 From: Snazzah Date: Tue, 5 Nov 2024 13:52:42 -0600 Subject: [PATCH] fix(tasks): handle patreon ratelimits --- apps/tasks/src/jobs/refreshPatrons.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/tasks/src/jobs/refreshPatrons.ts b/apps/tasks/src/jobs/refreshPatrons.ts index fd979ba..13040e8 100644 --- a/apps/tasks/src/jobs/refreshPatrons.ts +++ b/apps/tasks/src/jobs/refreshPatrons.ts @@ -62,7 +62,7 @@ export default class RefreshPatrons extends TaskJob { return credentials; } - async getPatrons(credentials: Credentials, cursor?: string) { + async getPatrons(credentials: Credentials, cursor?: string, retries = 0): Promise<{ patrons: Patron[]; next: string | undefined; total: number }> { const query = new URLSearchParams({ include: 'currently_entitled_tiers,user', 'fields[member]': 'full_name,currently_entitled_amount_cents,patron_status,email', @@ -73,9 +73,18 @@ export default class RefreshPatrons extends TaskJob { headers: { Authorization: `Bearer ${credentials.accessToken}`, 'User-Agent': this.userAgent - } + }, + validateStatus: () => true }); + if (response.status === 429) { + const waitFor = Math.pow(5, retries + 1); + if (retries >= 3) throw new Error('Too many rate limit retries when fetching patrons'); + this.logger.log(`Hit a 429, waiting ${waitFor} seconds to retry...`); + await new Promise((r) => setTimeout(r, waitFor * 1000)); + return this.getPatrons(credentials, cursor, retries + 1); + } else if (response.status !== 200) throw new Error(`Failed to fetch patrons: HTTP ${response.status}`); + const data = response.data as PatronCampaignMembersResponse; const patrons = data.data.map((member) => { const userId = member.relationships.user.data.id; @@ -92,6 +101,7 @@ export default class RefreshPatrons extends TaskJob { tiers: member.relationships.currently_entitled_tiers.data.map((tier) => tier.id) } as Patron; }); + return { patrons, next: data.meta.pagination.cursors?.next,