diff --git a/packages/frontend/src/actors/TokenActor.ts b/packages/frontend/src/actors/TokenActor.ts index 3c5351a..60ffb7d 100644 --- a/packages/frontend/src/actors/TokenActor.ts +++ b/packages/frontend/src/actors/TokenActor.ts @@ -1,36 +1,50 @@ -import { Unit, unit, minutes } from "itu-utils"; +// packages/frontend/src/actors/TokenActor.ts + +import { Unit, unit } from "itu-utils"; import { Actor, ActorRef, ActorSystem } from "ts-actors"; import Axios from "axios"; import { cookie } from "../utils"; -const updateToken = () => { - const hasToken = !!cookie("bearer"); - if (hasToken) { - Axios.get(import.meta.env.VITE_BACKEND_URI + "/auth/refresh", { withCredentials: true }).catch(() => { - alert( - "Could not refresh token. Presumeably the authentication server is unavailable. Please report this error if it happens repeatedly." - ); - window.location.href = "/"; - }); - } -}; - export class TokenActor extends Actor { - public interval: any; + public interval: any; + private expiresAt: Date; + + public constructor(name: string, system: ActorSystem) { + super(name, system); + this.expiresAt = new Date(); // Initialize with a default value + } + + public override async afterStart(): Promise { + this.updateToken(); + } - public constructor(name: string, system: ActorSystem) { - super(name, system); - } + public override async beforeShutdown(): Promise { + clearTimeout(this.interval); + } - public override async afterStart(): Promise { - this.interval = setInterval(updateToken, minutes(import.meta.env.VITE_INACTIVITY_LIMIT).valueOf()); - } + private updateToken = () => { + const hasToken = !!cookie("bearer"); + if (hasToken) { + Axios.get(import.meta.env.VITE_BACKEND_URI + "/auth/refresh", { withCredentials: true }) + .then(response => { + this.expiresAt = new Date(response.data.expires_at); + this.scheduleNextUpdate(); + }) + .catch(error => { + console.error("Failed to refresh token:", error); + setTimeout(this.updateToken, 5000); // Retry after 5 seconds + }); + } + }; - public override async beforeShutdown(): Promise { - clearInterval(this.interval); - } + private scheduleNextUpdate = () => { + const buffer = 30000; // 30 seconds before expiry + const delay = this.expiresAt.getTime() - Date.now() - buffer; + clearTimeout(this.interval); // Clear previous timeout + this.interval = setTimeout(this.updateToken, delay); + }; - public async receive(_from: ActorRef, _message: unknown): Promise { - return unit(); - } -} + public async receive(_from: ActorRef, _message: unknown): Promise { + return unit(); + } +} \ No newline at end of file