add health checking metadata, ios errors

This commit is contained in:
localhost 2025-11-17 20:09:16 +01:00
parent a3c727319b
commit aab9d6251f
5 changed files with 56 additions and 6 deletions

View File

@ -1,5 +1,6 @@
import { Elysia } from 'elysia'; import { Elysia } from 'elysia';
import { m, eta, error } from '@/utils/html' import { m, eta, error } from '@/utils/html'
import healthStatus from '@/utils/health';
const app = new Elysia() const app = new Elysia()
app.get('/', async ({ set }) => { app.get('/', async ({ set }) => {
@ -14,10 +15,15 @@ app.get('/', async ({ set }) => {
app.get('/save', async ({ query: { url }, set, error }) => { app.get('/save', async ({ query: { url }, set, error }) => {
if (!url) return error(400, 'No url provided.') if (!url) return error(400, 'No url provided.')
let websocket = process.env.WEBSOCKET
if (healthStatus[process.env.METADATA!] != 'healthy') {
websocket = process.env.ALTERNATIVE_WEBSOCKET!
}
set.headers['Content-Type'] = 'text/html; charset=utf-8' set.headers['Content-Type'] = 'text/html; charset=utf-8'
return await m(eta.render('./save', { return await m(eta.render('./save', {
title: 'Save Video | PreserveTube', title: 'Save Video | PreserveTube',
websocket: process.env.WEBSOCKET, websocket,
sitekey: process.env.SITEKEY, sitekey: process.env.SITEKEY,
url url
})) }))
@ -26,10 +32,15 @@ app.get('/save', async ({ query: { url }, set, error }) => {
app.get('/savechannel', async ({ query: { url }, set, error }) => { app.get('/savechannel', async ({ query: { url }, set, error }) => {
if (!url) return error(400, 'No url provided.') if (!url) return error(400, 'No url provided.')
let websocket = process.env.WEBSOCKET
if (healthStatus[process.env.METADATA!] != 'healthy') {
websocket = process.env.ALTERNATIVE_WEBSOCKET!
}
set.headers['Content-Type'] = 'text/html; charset=utf-8' set.headers['Content-Type'] = 'text/html; charset=utf-8'
return await m(eta.render('./savechannel', { return await m(eta.render('./savechannel', {
title: 'Save Channel | PreserveTube', title: 'Save Channel | PreserveTube',
websocket: process.env.WEBSOCKET, websocket,
sitekey: process.env.SITEKEY, sitekey: process.env.SITEKEY,
url url
})) }))

View File

@ -21,6 +21,10 @@
const h3 = document.getElementById("bottom") const h3 = document.getElementById("bottom")
const captcha = document.getElementById("captcha") const captcha = document.getElementById("captcha")
ws.onopen = function () {
document.querySelector("footer").innerHTML = `page rendered by <code><%= hostname %></code>, connected via <code>${websocket.split('-')[1].split('.')[0]}</code>`
}
ws.onmessage = function (msg) { ws.onmessage = function (msg) {
const text = msg.data.split(' - ').slice(1).join(' - ') const text = msg.data.split(' - ').slice(1).join(' - ')

View File

@ -18,6 +18,10 @@
const h3 = document.getElementById("bottom") const h3 = document.getElementById("bottom")
const captcha = document.getElementById("captcha") const captcha = document.getElementById("captcha")
ws.onopen = function () {
document.querySelector("footer").innerHTML = `page rendered by <code><%= hostname %></code>, connected via <code>${websocket.split('-')[1].split('.')[0]}</code>`
}
ws.onmessage = function (msg) { ws.onmessage = function (msg) {
const text = msg.data.split(' - ').slice(1).join(' - ') const text = msg.data.split(' - ').slice(1).join(' - ')

View File

@ -218,6 +218,10 @@
function initVideoLoading() { function initVideoLoading() {
const video = document.getElementById('video-player'); const video = document.getElementById('video-player');
const loading = document.getElementById('video-loading'); const loading = document.getElementById('video-loading');
let hasTheVideoErrored = false
const isIOSOrIPad = /iPad|iPhone|iPod/.test(navigator.userAgent) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
if (!video || !loading) return; if (!video || !loading) return;
loading?.classList.remove("hidden"); loading?.classList.remove("hidden");
@ -239,10 +243,17 @@
video.addEventListener('pointerdown', hide); video.addEventListener('pointerdown', hide);
video.addEventListener('error', () => { video.addEventListener('error', () => {
hasTheVideoErrored = true
loading.innerHTML = 'Video failed to load.'; loading.innerHTML = 'Video failed to load.';
loading.innerHTML += '<p style="font-size: medium;">This is not supposed to happen. Please email me at admin@preservetube.com with as much debugging information.</p>' +
'<p style="font-size: medium;">Please include your browser console logs. <a style="font-style: italic;" href="https://support.happyfox.com/kb/article/882-accessing-the-browser-console-and-network-logs/">' + if (isIOSOrIPad) {
'See here on how to access them.</a> Please note you might have to refresh the page for anything to show up.</p>' loading.innerHTML += '<p style="font-size: medium;">It looks like you\'re on an iOS or iPadOS device. Apple devices without a hardware decoder can\'t play the kind of video Preservetube serves.</p>' +
'<p style="font-size: medium;">Please try using a different device.</p>'
} else {
loading.innerHTML += '<p style="font-size: medium;">This is not supposed to happen. Please email me at admin@preservetube.com with as much debugging information.</p>' +
'<p style="font-size: medium;">Please include your browser console logs. <a style="font-style: italic;" href="https://support.happyfox.com/kb/article/882-accessing-the-browser-console-and-network-logs/">' +
'See here on how to access them.</a> Please note you might have to refresh the page for anything to show up.</p>'
}
}); });
// video already has data (i.e. cached) // video already has data (i.e. cached)
@ -251,7 +262,7 @@
// add an extra message after 10s // add an extra message after 10s
const FALLBACK_MS = 10000; const FALLBACK_MS = 10000;
const fallbackTimer = setTimeout(() => { const fallbackTimer = setTimeout(() => {
if (!loading.classList.contains('hidden')) { if (!loading.classList.contains('hidden') && !hasTheVideoErrored) {
loading.innerHTML = 'Taking longer than usual to load...'; loading.innerHTML = 'Taking longer than usual to load...';
loading.innerHTML += '<p style="font-size: medium;">This might be due one of multiple reasons:</p>' loading.innerHTML += '<p style="font-size: medium;">This might be due one of multiple reasons:</p>'
+ '<ol style="font-size: medium;"><li>This video is large. Depending on your browser, it might try loading the full thing at one time, which will slow things down.</li>' + '<ol style="font-size: medium;"><li>This video is large. Depending on your browser, it might try loading the full thing at one time, which will slow things down.</li>'

20
src/utils/health.ts Normal file
View File

@ -0,0 +1,20 @@
const healthStatus: Record<string, string> = {}
async function checkHealth() {
const metadataServers: string[] = [process.env.METADATA!, process.env.ALTERNATIVE_METADATA!]
await Promise.all(metadataServers.map(async (m) => {
try {
const req = await fetch(m + '/health')
healthStatus[m] = req.ok ? 'healthy' : 'unhealthy'
} catch (_) {
healthStatus[m] = 'unhealthy'
}
}))
console.log(`checked health status - ${Object.entries(healthStatus).map(h => `${h[0].split('-')[1].split('.')[0]} ${h[1]}`).join(', ')}`)
}
checkHealth()
setInterval(checkHealth, 5 * 60000)
export default healthStatus