Stratégie de cache PWA : timestamp ?

WRInaute accro
Bonjour

Problème de cache pour une PWA :

J'imagine ceci :

Le contenu en cache a sa première ligne => timestamp server & timestamp client.

Ces timestamp sont enregistrés par le dernier fetch.

Le smartphone ne connait que le timestamp client au moment de la lecture du cache, et sa longitude peut avoir changé depuis le dernier fetch.

Comment évaluer les timestamps, si le cache ne doit, par ex., pas être plus vieux que 120 minutes ?

Merci beaucoup de votre aide.
 
WRInaute accro
Pardon

2 solutions :

Date.now() qui ne tient pas compte des "secondes intercalaires" ou "leap seconds",

TC39 Temporal qui en tient compte mais est encore en développement.

Pour un simple cache, Date.now() est largement suffisant ?

Merci beaucoup.
 
WRInaute passionné
Première fois que je vois quelqu'un se prendre la tête pour les secondes intercalaires...
La dernière qui a été ajoutée a été en 2016.
Et que le cache soit alors à 120 ou 119 secondes à ce moment-là ne va pas perturber les utilisateurs...
 
WRInaute accro
Voilà, voilà.

Merci des avis et critiques.

Pour l'intant, seules les response sont données, pas les data.

C'est pour plus de modularité.

Pas testé.

Bien amicalement.


JavaScript:
// "use strict";
const CACHE_MAX = 200000;
function inArray(needle, haystack) {
 let i; const len = haystack.length;
 for (i = 0; i < len; i += 1) {
  if (haystack[i].includes(needle)) {
   return true;
  }
 }
 return false;
}
const CACHE_NAME = 'cache-v1'; const FILES_TO_CACHE = [];
/*****************/
/**    INSTALL  **/
/*****************/
self.addEventListener('install', (event) => {
 console.log('[ServiceWorker] Install');
 // Precache static resources here.
 event.waitUntil(
  caches.open(CACHE_NAME).then((cache) => {
   console.log('[ServiceWorker] Pre-caching offline page');
   return cache.addAll(FILES_TO_CACHE);
  }),
 );
 self.skipWaiting();
});
/*******************/
/**    ACTIVATE   **/
/*******************/
self.addEventListener('activate', (event) => {
 console.log('[ServiceWorker] Activate');
 // Remove previous cached data from disk.
 event.waitUntil(
  caches.keys().then((keyList) => Promise.all(keyList.map((key) => {
   if (key !== CACHE_NAME) {
    console.log('[ServiceWorker] Removing old cache', key);
    return caches.delete(key);
   }
  }))),
 );
 self.clients.claim();
});
/****************/
/**     FETCH  **/
/****************/
function resolve(response) {
 let maintenant = Date.now();
 let delta = maintenant - parseInt(response.clone().slice(0, response.clone().indexOf('\n')), 10);
 if (delta > CACHE_MAX) {
  return fetch(event.request).then((response2) => {
   let newResponse = response2.clone().replace(/^[0-9]+\n/, maintenant);
   cache.put(event.request, newResponse);
  }).then((response) => // fetch(event.request).then(function (response)
   response);
 } // if (delta > CACHE_MAX)
 return response;
}
function reject(error) {
 console.log(`Erreur : ${error}`);
 let maintenant = Date.now();
 return fetch(event.request).then((response3) => {
  let newResponse2 = response3.clone().replace(/^[0-9]+\n/, maintenant);
  cache.put(event.request, newResponse2);
  return response3;
 });
}
self.addEventListener('fetch', (event) => {
 console.log(`[ServiceWorker] Fetch ${event.request.url} in ${event.request.method}`);
 //  Autres conditions/caches après.
 if (inArray(event.request.url, FILES_TO_CACHE) !== true) {
  if (event.request.url.includes('statistiques')) {
   event.respondWith(
    fetch(event.request).then((response) => response).then((response) => // fetch(event.request).then(function (response)
     response).catch((error) => {
      console.log(`Erreur : ${error}`);
     }),
   ); // event.respondWith(
  } // if (event.request.url.includes("statistiques"))
  event.respondWith(
   maPromise = new Promise((resolve, reject) => {
    caches.open(CACHE_NAME).then((cache) => cache.match(event.request).then((response) => resolve(response)).catch((error) => reject(error)).catch((error) => {
     console.log(`Erreur : ${error}`);
    }));
   }),
  ); // event.respondWith(
 }
});
 
WRInaute accro
Plus généralement :

Est-il possible d'associer une variable/timestamp à une ressource en cache ?

Evidemment, de lire et écrire dessus.

Amicalement.
 
WRInaute accro
Rebonjour

Est-il possible d'enregistrer une variable dans le cache ?

Genre :


JavaScript:
const CACHE_KEY_PREFIX = 'XYZT_';

self.addEventListener('fetch', function(event) {
 let Request = event.request;
 let cacheRequest =  new Request(CACHE_KEY_PREFIX + Request.url);
 let maintenant = Date.now();
    caches.open(CACHE_NAME).then(function(cache) {
            timestamp = parseInt(timestamp, 10);
            cache.put(cacheRequest, maintenant);
        }      
}

Comme le cache fait correspondre une Request clé à une valeur, est-ce que ce hack est valide ?

Merci beaucoup.
 
WRInaute accro
Pardon

Il y a une autre solution que le timestamp.

C'est l'équivalent de l'ETag.

Soit dans le header soit en lecture d'une url associée à l'url à charger.

Si c'est dans le header, je suis obligé de lire aussi le body.

Si c'est une autre url, comment côté serveur, présenter de manière automatique, un ETag hash code de l'url initiale ?

Merci beaucoup.

Amicalement.
 
WRInaute accro
Repardon.

J'ai récupéré dans mes fichiers l'algorithme complet de cache HTTP.

Je vais l'implémenter dans class_cache_inc.php ( merci à Noren ) pour mon site, et puis ma PWA.

Bien amicalement.
 
WRInaute accro
Bonjour nicodak

Parmi les headers à prendre en compte, le Cache-Control n'est-il pas plus ou moins obsolète ?

Même chose pour le Expires?

Pour un "Cache-Control: max-age=n" et n fixe, le browser adapte son header client Age ad hoc ?

Merci beaucoup.
 
Discussions similaires
Haut