Merge pull request #7: Stop caching index.html and speed up socket reconnect
This commit is contained in:
commit
07c17fbd2c
3 files changed
+33
-6
No files matched your search
@@ -4,7 +4,22 @@ server {
|
|||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
|
# Hashed Vite assets are immutable; cache them hard.
|
||||||
|
location /assets/ {
|
||||||
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# The HTML entry point must never be cached, or a phone (which offers no
|
||||||
|
# easy hard-refresh) keeps loading an old bundle after a deploy. The
|
||||||
|
# catch-all serves index.html for client-side routes, so it gets the same
|
||||||
|
# no-store header.
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control "no-store";
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
add_header Cache-Control "no-store";
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -36,6 +36,7 @@ const events = ref([])
|
|||||||
const equityPoints = ref([])
|
const equityPoints = ref([])
|
||||||
const busy = ref(false)
|
const busy = ref(false)
|
||||||
const connected = ref(false)
|
const connected = ref(false)
|
||||||
|
const socketError = ref('')
|
||||||
|
|
||||||
let socket
|
let socket
|
||||||
let pollTimer
|
let pollTimer
|
||||||
@@ -132,8 +133,15 @@ onMounted(async () => {
|
|||||||
])
|
])
|
||||||
socket = api.openSocket({
|
socket = api.openSocket({
|
||||||
onMessage: handleMessage,
|
onMessage: handleMessage,
|
||||||
onOpen: () => (connected.value = true),
|
onOpen: () => {
|
||||||
|
connected.value = true
|
||||||
|
socketError.value = ''
|
||||||
|
},
|
||||||
onClose: () => (connected.value = false),
|
onClose: () => (connected.value = false),
|
||||||
|
onError: (code) => {
|
||||||
|
if (code === 1008) socketError.value = 'rejected by the server (token/auth)'
|
||||||
|
else socketError.value = `socket closed (code ${code})`
|
||||||
|
},
|
||||||
})
|
})
|
||||||
pollTimer = setInterval(refreshAll, 5000)
|
pollTimer = setInterval(refreshAll, 5000)
|
||||||
})
|
})
|
||||||
@@ -161,6 +169,7 @@ onUnmounted(() => {
|
|||||||
:class="connected ? 'bg-emerald-400' : 'bg-slate-500'"
|
:class="connected ? 'bg-emerald-400' : 'bg-slate-500'"
|
||||||
></span>
|
></span>
|
||||||
{{ connected ? 'live' : 'reconnecting' }}
|
{{ connected ? 'live' : 'reconnecting' }}
|
||||||
|
<span v-if="!connected && socketError" class="text-amber-300">· {{ socketError }}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xs text-slate-400">
|
<div class="text-xs text-slate-400">
|
||||||
|
|||||||
+8
-5
@@ -26,7 +26,7 @@ export const getPresets = () => http.get('/presets').then((r) => r.data)
|
|||||||
export const createPreset = (payload) => http.post('/presets', payload).then((r) => r.data)
|
export const createPreset = (payload) => http.post('/presets', payload).then((r) => r.data)
|
||||||
export const deletePreset = (id) => http.delete(`/presets/${id}`).then((r) => r.data)
|
export const deletePreset = (id) => http.delete(`/presets/${id}`).then((r) => r.data)
|
||||||
|
|
||||||
export function openSocket({ onMessage, onOpen, onClose }) {
|
export function openSocket({ onMessage, onOpen, onClose, onError }) {
|
||||||
const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'
|
const proto = window.location.protocol === 'https:' ? 'wss' : 'ws'
|
||||||
const url = `${proto}://${window.location.host}/api/ws`
|
const url = `${proto}://${window.location.host}/api/ws`
|
||||||
let socket
|
let socket
|
||||||
@@ -36,9 +36,9 @@ export function openSocket({ onMessage, onOpen, onClose }) {
|
|||||||
|
|
||||||
const schedule = () => {
|
const schedule = () => {
|
||||||
if (closed) return
|
if (closed) return
|
||||||
// Back off from 2s up to 30s so a persistently failing socket (e.g. auth)
|
// Retry at 1s, then back off up to 30s so a persistently failing socket
|
||||||
// does not hammer the server, while a brief blip still reconnects fast.
|
// does not hammer the server while a brief blip recovers immediately.
|
||||||
const delay = Math.min(2000 * 2 ** attempt, 30000)
|
const delay = Math.min(1000 * 2 ** attempt, 30000)
|
||||||
attempt += 1
|
attempt += 1
|
||||||
retryTimer = setTimeout(connect, delay)
|
retryTimer = setTimeout(connect, delay)
|
||||||
}
|
}
|
||||||
@@ -51,8 +51,11 @@ export function openSocket({ onMessage, onOpen, onClose }) {
|
|||||||
onOpen?.()
|
onOpen?.()
|
||||||
}
|
}
|
||||||
socket.onmessage = (event) => onMessage?.(JSON.parse(event.data))
|
socket.onmessage = (event) => onMessage?.(JSON.parse(event.data))
|
||||||
socket.onclose = () => {
|
socket.onclose = (event) => {
|
||||||
onClose?.()
|
onClose?.()
|
||||||
|
// 1008 = policy violation (token rejected); 1006 = abnormal close, which
|
||||||
|
// is what an auth/proxy rejection looks like to the browser.
|
||||||
|
onError?.(event.code, event.reason)
|
||||||
schedule()
|
schedule()
|
||||||
}
|
}
|
||||||
socket.onerror = () => socket.close()
|
socket.onerror = () => socket.close()
|
||||||
|
|||||||
Reference in new issue
Block a user