From 8a3132321293815219d748c8977c8d1319a9d168 Mon Sep 17 00:00:00 2001 From: Jasper Mayone Date: Tue, 8 Jul 2025 21:24:28 -0400 Subject: [PATCH] better rate limit handling --- main.ts | 62 ++++++++++++++++++++++++++++++++++++----------- package-lock.json | 4 +-- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/main.ts b/main.ts index ad927c2..8b0553a 100644 --- a/main.ts +++ b/main.ts @@ -233,6 +233,8 @@ class LimitlessAPI { private apiKey: string; private baseUrl = 'https://api.limitless.ai'; private batchSize = 10; + private maxRetries = 5; + private retryDelay = 1000; // 1 second constructor(apiKey: string) { this.apiKey = apiKey; @@ -261,20 +263,7 @@ class LimitlessAPI { } try { - const response = await requestUrl({ - url: `${this.baseUrl}/v1/lifelogs?${params.toString()}`, - method: 'GET', - headers: { - 'X-API-Key': this.apiKey, - 'Content-Type': 'application/json' - } - }); - - if (!response.json) { - throw new Error('Invalid response format'); - } - - const data = response.json; + const data = await this.makeRequest(`${this.baseUrl}/v1/lifelogs`, params); const lifelogs = data.data?.lifelogs || []; allLifelogs.push(...lifelogs); @@ -287,4 +276,49 @@ class LimitlessAPI { return allLifelogs; } + + private async makeRequest(url: string, params: URLSearchParams): Promise { + let retries = 0; + while (true) { + try { + const response = await requestUrl({ + url: `${url}?${params.toString()}`, + method: 'GET', + headers: { + 'X-API-Key': this.apiKey, + 'Content-Type': 'application/json' + } + }); + + if (!response.json) { + throw new Error('Invalid response format'); + } + + return response.json; + } catch (error) { + if (error.status === 429 && retries < this.maxRetries) { + let delay = this.retryDelay * Math.pow(2, retries); + const retryAfter = error.headers?.['retry-after']; + + if (retryAfter) { + const retryAfterSeconds = parseInt(retryAfter, 10); + if (!isNaN(retryAfterSeconds)) { + delay = retryAfterSeconds * 1000; + } else { + const retryAfterDate = new Date(retryAfter); + const now = new Date(); + delay = retryAfterDate.getTime() - now.getTime(); + } + } + + new Notice(`Rate limit exceeded. Retrying in ${Math.round(delay / 1000)} seconds...`); + await new Promise(resolve => setTimeout(resolve, delay)); + retries++; + } else { + console.error('Error making request:', error); + throw error; + } + } + } + } } diff --git a/package-lock.json b/package-lock.json index c57ad20..1cb59f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-limitless-lifelogs", - "version": "1.0.4", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "obsidian-limitless-lifelogs", - "version": "1.0.4", + "version": "1.0.5", "license": "MIT", "devDependencies": { "@types/node": "^16.11.6",