use server sent events instead of polling
All checks were successful
Build Container / Build Container (push) Successful in 1m27s

This commit is contained in:
kritzl 2026-05-19 17:09:02 +02:00
commit 8281848215
Signed by: kritzl
SSH key fingerprint: SHA256:5BmINP9VjZWaUk5Z+2CTut1KFhwLtd0ZynMekKbtViM
2 changed files with 90 additions and 46 deletions

View file

@ -1,5 +1,5 @@
import {Fetcher} from "openapi-typescript-fetch"
import type {paths} from "../api/schema"
import type {components, paths} from "../api/schema"
import type {ui} from "../i18n/ui.ts"
const fetcher = Fetcher.for<paths>()
@ -29,7 +29,7 @@ declare global {
lang: keyof typeof ui;
doors: Array<DoorType>;
auth: AuthType;
doorAction: (action: 'unlock' | 'lock', doorId: string) => void;
doorAction: (action: "unlock" | "lock", doorId: string) => void;
}
}
@ -105,18 +105,18 @@ async function checkUser() {
if (e instanceof getUserInfo.Error) {
const error = e.getActualType()
if (error.status === 401) {
if (!auth.recentLogout)
auth.recentLogout = auth.authenticated // set recentLogout true, if user was logged in before
auth.authenticated = false
auth.authorized = false
auth.until = null
auth.username = ""
} else if (error.status >= 500 && error.status < 600) {
if (error.status >= 500 && error.status < 600) {
apiError.current = "serverError"
} else {
console.error("unknown error:", error)
}
if (!auth.recentLogout)
auth.recentLogout = auth.authenticated // set recentLogout true, if user was logged in before
auth.authenticated = false
auth.authorized = false
auth.until = null
auth.username = ""
}
} finally {
localStorage.setItem("auth", JSON.stringify(auth))
@ -125,15 +125,24 @@ async function checkUser() {
}
}
async function fetchDoors() {
async function subscribeDoorEvents() {
if (doors.length === 0) {
loading.doors = true
}
refresh()
const getDoors = fetcher.path("/api/locks/").method("get").create()
try {
const {data: doorInfo} = await getDoors({})
const evtSource = new EventSource("/api/locks/stream")
evtSource.onerror = () => {
if (!window.navigator.onLine) {
apiError.current = "networkError"
} else {
apiError.current = "serverError"
}
}
evtSource.onmessage = (event) => {
const doorInfo: Array<components["schemas"]["Lock"]> = JSON.parse(event.data)
apiError.current = null
while (doors.length) {
@ -164,29 +173,6 @@ async function fetchDoors() {
loading.doors = false
refresh()
} catch (e) {
// check which operation threw the exception
if (e instanceof getDoors.Error) {
const error = e.getActualType()
if (error.status === 401) {
console.log("unauthorized")
loading.doors = false
refresh()
} else if (error.status >= 500 && error.status < 600) {
apiError.current = "serverError"
clearInterval(doorsInterval)
} else {
console.error("unknown error:", error)
}
}
if (e instanceof Error) {
switch (e.name) {
case "TypeError":
apiError.current = "networkError"
}
}
}
}
@ -295,7 +281,7 @@ function refresh() {
loadAuthFromLocalStorage()
const doorsInterval = setInterval(fetchDoors, 250) // TODO: replace with SSE
subscribeDoorEvents()
checkUser()
document.addEventListener("loadeddata", () => {