fix(falukant): revalidate replaced character meshes
All checks were successful
Deploy to production / deploy (push) Successful in 1m55s

This commit is contained in:
Torsten Schulz (local)
2026-09-30 14:40:50 +02:00
parent 6d14038dad
commit c02bc07265
2 changed files with 9 additions and 2 deletions

View File

@@ -14,7 +14,10 @@ router.get('/3d/falukant/characters/:filename', async (req, res) => {
try {
const cachePath = await getOptimizedModelPath(filename);
res.setHeader('Content-Type', 'model/gltf-binary');
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
// GLB files can be replaced under the same filename during an asset deploy.
// Revalidate cached copies so clients receive a changed mesh without needing
// to clear their browser cache.
res.setHeader('Cache-Control', 'public, max-age=0, must-revalidate');
res.sendFile(cachePath);
} catch (e) {
if (e.message?.includes('Invalid model filename') || e.message?.includes('not found')) {

View File

@@ -27,6 +27,10 @@ import { getApiBaseURL } from '@/utils/axios.js';
/** Backend-Route: GET /api/models/3d/falukant/characters/:filename (Proxy mit Draco-Optimierung) */
const MODELS_API_PATH = '/api/models/3d/falukant/characters';
const OPTIMIZED_MODEL_SUFFIX = '_opt.glb';
// Bump this when deployment replaces GLB files under unchanged filenames.
// The revision is part of the URL, so a browser cannot reuse an older immutable
// response for the same model file.
const MODEL_ASSET_REVISION = '20260930-2';
// Only concrete age models are used. If an exact age is not available, choose
// the nearest lower one instead of the generic gender/age-group fallback.
const AVAILABLE_MODEL_AGES = Object.freeze({
@@ -456,7 +460,7 @@ export default {
.filter((age) => age <= modelAge)
.sort((left, right) => right - left);
const candidates = candidateAges.map((age) =>
`${prefix}/${this.actualGender}_${age}y${OPTIMIZED_MODEL_SUFFIX}`
`${prefix}/${this.actualGender}_${age}y${OPTIMIZED_MODEL_SUFFIX}?v=${MODEL_ASSET_REVISION}`
);
let gltf;