Fix Vaultwarden 429: add 5min server cache, slow widget poll
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-05-16 17:22:36 +02:00
parent 221fa810c9
commit fdf616d5e8
2 changed files with 14 additions and 3 deletions
+13 -2
View File
@@ -6,6 +6,10 @@ const router = Router()
let vwCookie: string | null = null let vwCookie: string | null = null
let vwCookieExpiry = 0 let vwCookieExpiry = 0
interface CacheEntry { data: unknown; ts: number }
let statsCache: CacheEntry | null = null
const CACHE_TTL = 5 * 60 * 1000 // 5 minutes
async function getCookie(): Promise<string> { async function getCookie(): Promise<string> {
if (vwCookie && Date.now() < vwCookieExpiry) return vwCookie if (vwCookie && Date.now() < vwCookieExpiry) return vwCookie
@@ -38,6 +42,11 @@ router.get('/stats', async (_req, res) => {
const host = process.env.VAULTWARDEN_HOST const host = process.env.VAULTWARDEN_HOST
if (!host) { res.status(503).json({ error: 'VAULTWARDEN_HOST not configured' }); return } if (!host) { res.status(503).json({ error: 'VAULTWARDEN_HOST not configured' }); return }
if (statsCache && Date.now() - statsCache.ts < CACHE_TTL) {
res.json(statsCache.data)
return
}
const cookie = await getCookie() const cookie = await getCookie()
const [usersRes, diagRes] = await Promise.all([ const [usersRes, diagRes] = await Promise.all([
@@ -59,7 +68,7 @@ router.get('/stats', async (_req, res) => {
const users: any[] = usersRes.data ?? [] const users: any[] = usersRes.data ?? []
const diag = diagRes.data ?? {} const diag = diagRes.data ?? {}
res.json({ const result = {
version: diag.version ?? null, version: diag.version ?? null,
signupsAllowed: diag.config?.signups_allowed ?? null, signupsAllowed: diag.config?.signups_allowed ?? null,
userCount: users.length, userCount: users.length,
@@ -73,7 +82,9 @@ router.get('/stats', async (_req, res) => {
cipherCount: u.cipherCount ?? u.cipher_count ?? null, cipherCount: u.cipherCount ?? u.cipher_count ?? null,
attachCount: u.attachmentCount ?? u.attachment_count ?? null, attachCount: u.attachmentCount ?? u.attachment_count ?? null,
})), })),
}) }
statsCache = { data: result, ts: Date.now() }
res.json(result)
} catch (err: unknown) { } catch (err: unknown) {
if (err instanceof Error && err.message.includes('login failed')) vwCookie = null if (err instanceof Error && err.message.includes('login failed')) vwCookie = null
const msg = err instanceof Error ? err.message : 'Unknown error' const msg = err instanceof Error ? err.message : 'Unknown error'
+1 -1
View File
@@ -18,7 +18,7 @@ function formatDate(iso: string | null): string {
} }
export function VaultwardenWidget() { export function VaultwardenWidget() {
const { data, loading, error } = useApi<VaultwardenData>('/api/vaultwarden/stats') const { data, loading, error } = useApi<VaultwardenData>('/api/vaultwarden/stats', 5 * 60_000)
return ( return (
<div className="card"> <div className="card">