Skip to content

Commit

Permalink
Add retries to BGG
Browse files Browse the repository at this point in the history
  • Loading branch information
sitegui committed Sep 11, 2024
1 parent 634964d commit 8d4d32b
Showing 1 changed file with 31 additions and 14 deletions.
45 changes: 31 additions & 14 deletions src/board_game_geek.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { sleep } from '@/helpers'
const BASE_URL = 'https://www.boardgamegeek.com/xmlapi2'
const REQUEST_TIMEOUT = 10e3
const EXPORT_COLLECTION_QUEUE_TIMEOUT = 120e3
const EXPORT_COLLECTION_QUEUE_SLEEP = 6e3
const EXPORT_COLLECTION_QUEUE_SLEEP = 2e3
const EXPORT_COLLECTION_QUEUE_TRIES = 3
const GET_GAMES_BATCH_SIZE = 10
const GET_GAMES_BATCH_SLEEP = 2e3
const GET_GAMES_BATCH_SLEEP = 1e3
const GET_GAMES_BATCH_TRIES = 3
const RETRY_SLEEP = 5e3

/**
* Represents a board game retrieved from BoardGameGeek API.
Expand Down Expand Up @@ -58,7 +61,7 @@ export async function listGamesInUserCollection(

let response = null
while (Date.now() - start < EXPORT_COLLECTION_QUEUE_TIMEOUT) {
response = await fetchWithTimeout(apiUrl, REQUEST_TIMEOUT)
response = await fetchWithTimeout(apiUrl, REQUEST_TIMEOUT, EXPORT_COLLECTION_QUEUE_TRIES)
if (response.status !== 202) {
break
}
Expand Down Expand Up @@ -180,27 +183,41 @@ export async function searchGames(term: string): Promise<BggSearchHit[]> {
return searchHits
}

async function fetchWithTimeout(url: string, time: number): Promise<Response> {
const controller = new AbortController()
const signal = controller.signal
async function fetchWithTimeout(url: string, time: number, tries: number = 1): Promise<Response> {
for (let i = 0; i < tries; i++) {
const controller = new AbortController()
const signal = controller.signal

const timeout = setTimeout(() => {
controller.abort()
}, time)
const timeout = setTimeout(() => {
controller.abort()
}, time)

const response = await fetch(url, { signal })

clearTimeout(timeout)
try {
const response = await fetch(url, { signal })
if (!response.ok) {
throw new Error(`BGG responded with ${response.status}`)
}
return response
} catch (error) {
if (i === tries - 1) {
throw error
}
console.warn(`BGG failed with ${error}, will try again`)
await sleep((i + 1) * RETRY_SLEEP)
} finally {
clearTimeout(timeout)
}
}

return response
throw new Error('Unreachable')
}

async function getGames(ids: string[], progressCallback: ProgressCallback): Promise<BggGame[]> {
const games: BggGame[] = []

const idsParam = encodeURIComponent(ids.join(','))
const apiUrl = `${BASE_URL}/things?id=${idsParam}&stats=1`
const response = await fetchWithTimeout(apiUrl, REQUEST_TIMEOUT)
const response = await fetchWithTimeout(apiUrl, REQUEST_TIMEOUT, GET_GAMES_BATCH_TRIES)

if (response.status !== 200) {
throw new Error(`BGG responded with ${response.status}`)
Expand Down

0 comments on commit 8d4d32b

Please sign in to comment.