trying to fix tag cache

This commit is contained in:
2026-05-13 02:12:02 +02:00
parent 3f743177d3
commit b0f648b71c
2 changed files with 36 additions and 21 deletions

View File

@@ -26,12 +26,17 @@ export async function regenerateTagImage(tag, mode) {
} }
const items = await db` const items = await db`
SELECT i.id SELECT id FROM (
FROM items i SELECT i.id
JOIN tags_assign ta ON ta.item_id = i.id FROM items i
JOIN tags t ON t.id = ta.tag_id JOIN tags_assign ta ON ta.item_id = i.id
${modeFilter} JOIN tags t ON t.id = ta.tag_id
WHERE (t.tag = ${tag} OR t.normalized = ${tag}) AND i.active = true ${modeFilter}
WHERE (t.tag = ${tag} OR t.normalized = ${tag})
AND i.active = true
AND i.is_deleted = false
LIMIT 100
) pool
ORDER BY RANDOM() ORDER BY RANDOM()
LIMIT 3 LIMIT 3
`; `;
@@ -139,16 +144,20 @@ function generateFallbackSvg(tag) {
} }
export default (router, tpl) => { export default (router, tpl) => {
router.get(/^\/tag_image\/(?<tag>.+)$/, async (req, res) => { router.get(/^\/tag_image\/(?<tag>[^?]+)$/, async (req, res) => {
const tag = decodeURIComponent(req.params.tag); const tag = decodeURIComponent(req.params.tag);
// Parse query parameters // Parse query parameters robustly
let query = {}; let query = {};
if (typeof req.url === 'string') { try {
const parsedUrl = url.parse(req.url, true); if (typeof req.url === 'string') {
query = parsedUrl.query; const parsedUrl = url.parse(req.url, true);
} else { query = parsedUrl.query;
query = req.url.qs || {}; } else if (req.url && req.url.qs) {
query = req.url.qs;
}
} catch (e) {
console.error('[TAG_IMAGE] Query parse failed:', e);
} }
const mode = query.m ? parseInt(query.m) : (req.mode ?? 0); const mode = query.m ? parseInt(query.m) : (req.mode ?? 0);
@@ -163,7 +172,8 @@ export default (router, tpl) => {
'Content-Type': 'image/webp', 'Content-Type': 'image/webp',
'Cache-Control': `public, max-age=${CACHE_MAX_AGE}` 'Cache-Control': `public, max-age=${CACHE_MAX_AGE}`
}); });
return res.end(await fs.readFile(cachePath)); const content = await fs.readFile(cachePath);
return res.end(content);
} }
} catch (e) { } catch (e) {
// Cache miss, proceed to generation // Cache miss, proceed to generation
@@ -172,11 +182,16 @@ export default (router, tpl) => {
// Generate on-demand // Generate on-demand
const generated = await regenerateTagImage(tag, mode); const generated = await regenerateTagImage(tag, mode);
if (generated) { if (generated) {
res.writeHead(200, { try {
'Content-Type': 'image/webp', const content = await fs.readFile(generated);
'Cache-Control': `public, max-age=${CACHE_MAX_AGE}` res.writeHead(200, {
}); 'Content-Type': 'image/webp',
return res.end(await fs.readFile(generated)); 'Cache-Control': `public, max-age=${CACHE_MAX_AGE}`
});
return res.end(content);
} catch (err) {
console.error(`[TAG_IMAGE] Failed to read generated file ${generated}:`, err);
}
} }
// Fallback to deterministic SVG // Fallback to deterministic SVG

View File

@@ -227,7 +227,7 @@ process.on('uncaughtException', err => {
return; return;
if (req.url.pathname === '/manifest.json' || req.url.pathname === '/sw.js') if (req.url.pathname === '/manifest.json' || req.url.pathname === '/sw.js')
return; return;
if (req.url.pathname.match(/^\/(b|t|ca|a|memes)\//) || req.url.pathname.startsWith('/s/emojis/')) { if (req.url.pathname.match(/^\/(b|t|ca|a|memes|tag_image)\//) || req.url.pathname.startsWith('/s/emojis/')) {
if (cfg.websrv.private_society && !req.cookies?.session) { if (cfg.websrv.private_society && !req.cookies?.session) {
res.writeHead(502, { 'Content-Type': 'text/html' }).end(nginx502); res.writeHead(502, { 'Content-Type': 'text/html' }).end(nginx502);
req.url.pathname = '/private_society_media_bypass'; req.url.pathname = '/private_society_media_bypass';
@@ -409,7 +409,7 @@ process.on('uncaughtException', err => {
// Private Society gate — require login for all content when enabled // Private Society gate — require login for all content when enabled
if (cfg.websrv.private_society && !req.session) { if (cfg.websrv.private_society && !req.session) {
const publicPaths = /^\/(s|login|logout|register|activate|forgot-password|reset-password|banned|api\/v2\/auth|manifest\.json|sw\.js|robots\.txt|favicon\.(ico|png|gif)|s\/img\/duck-icon-(192|512)\.png)(\/.*)?$/; const publicPaths = /^\/(s|tag_image|login|logout|register|activate|forgot-password|reset-password|banned|api\/v2\/auth|manifest\.json|sw\.js|robots\.txt|favicon\.(ico|png|gif)|s\/img\/duck-icon-(192|512)\.png)(\/.*)?$/;
if (!publicPaths.test(req.url.pathname)) { if (!publicPaths.test(req.url.pathname)) {
// For AJAX requests, return 502 so it looks like the backend is down // For AJAX requests, return 502 so it looks like the backend is down
if (req.headers['x-requested-with'] === 'XMLHttpRequest') { if (req.headers['x-requested-with'] === 'XMLHttpRequest') {