90 lines
2.6 KiB
TypeScript

import { useEngineStore } from "@/stores/EngineStore"
import { useUserinfoStore } from "@/stores/UserinfoStore"
import { useGameinfoStore } from "@/stores/GameinfoStore"
import { useRoundStore } from "@/stores/RoundStore"
import { usePlayersStore } from "@/stores/PlayersStore"
import { EngineContext } from '@/composables/useEngine'
type EngineResponse = {
version: string,
game: {
id: string,
name: string,
state: string,
phase: string,
round: any,
players: Array<any>,
},
}
export async function fetchUpdate(this: EngineContext) {
if (this.shouldStop || !this.isActive) {
this.isActive = false
this.shouldStop = false
console.debug('engine stopped')
return
}
let delay = 0
try {
const userInfoStore = useUserinfoStore()
const response = await this.callApi('/api/sync', {
v: '' + (this.version + 1),
g: userInfoStore.gameId,
}) as EngineResponse
if (!Number.isInteger(response.version)) {
throw Error('unexpected response from /api/sync')
}
this.version = parseInt(response.version)
this.isConnected.value = true
this.retry.value = 0
useEngineStore().setJson(response)
useGameinfoStore().setGameinfo(response.game)
useRoundStore().setRound(response.game.round)
usePlayersStore().setPlayers(response.game.players)
// apply rate limit
const now = new Date()
const last = this.lastFetched.splice(0, 1)
this.lastFetched.push(now)
if (now.getTime() - last[0].getTime() < 1000) {
console.warn('engine: respawning too fast, throttling down')
delay = 5000
}
} catch (e: any) {
this.isConnected.value = false
this.retry.value++
if (e.response) {
// callApi() threw an exception
const { status, statusText } = e.response
if (status == 200) {
delay = 1000
} else {
console.warn(`HTTP ${status} ${statusText}`)
if (this.retry.value <= 15) {
delay = 1000
} else {
delay = 5000
}
this.version = -1
}
} else {
// request aborted or other causes
console.warn(e.message)
this.retry.value = -1
this.isActive = false
this.shouldStop = false
console.debug('engine stopped')
return
}
}
window.setTimeout(() => {
this.fetchUpdate()
}, delay)
}