Récupération du Cache Obsolète Quand le Service Externe Perd des Données
Problème
Quand vous utilisez votre base de données comme couche de cache/idempotence (voir local-cache-idempotency-fallback),
un nouveau mode de défaillance apparaît : le service externe perd ou réinitialise ses données, mais votre
cache conserve les anciennes valeurs. Les opérations échouent avec des erreurs trompeuses parce que les identifiants en cache
n'existent plus sur le service externe.
Contexte / Conditions de Déclenchement
- L'actualisation du token échoue avec 404 « User with pubkey/id not found »
- Les opérations échouent avec « Invalid or expired token » mais le vrai problème est l'utilisateur manquant
- Le service externe a été réinitialisé, migré ou a perdu des données
- Les identifiants en cache (pubkeys, API keys, user IDs) sont valides en cache mais pas sur le service
- Le message d'erreur est trompeur - suggère un problème de token alors que c'est vraiment une ressource manquante
Solution
Détectez le cas spécifique « not found » et gérez-le séparément des autres erreurs :
if (cached) {
pubkey = cached.pubkey;
token = cached.token;
try {
// Try to refresh/validate the cached credentials
const freshToken = await externalApi.getTokenByPubkey(pubkey);
token = freshToken;
console.log(`Pubkey: ${pubkey} (token refreshed)`);
} catch (error) {
const errMsg = error instanceof Error ? error.message : String(error);
// CRITICAL: Detect "not found" specifically - cache is stale
if (errMsg.includes("not found") || response.status === 404) {
console.log(`Cached identifier not on external service, recreating...`);
// 1. Delete stale cache entry
await db.deleteUser(userId);
// 2. Create fresh resource on external service
const result = await externalApi.createUser(userId, username);
pubkey = result.pubkey;
token = result.token;
console.log(`Pubkey: ${pubkey} (recreated)`);
// 3. Cache new values
await db.saveUser({ userId, pubkey, token });
} else {
// Other error (e.g., user claimed account, rate limit) - can't proceed
console.log(`Refresh failed: ${errMsg}`);
continue; // or throw
}
}
}
Motif Clé
- Tentez d'abord l'actualisation normale : essayez de valider/actualiser les identifiants en cache
- Détectez 404 spécifiquement : vérifiez « not found » dans le message d'erreur ou le statut 404
- Supprimez l'entrée obsolète : supprimez l'entrée de cache invalide avant de recréer
- Recréez sur le service externe : créez une ressource fraîche avec les mêmes identifiants d'entrée
- Mettez à jour le cache : stockez les nouvelles valeurs pour les exécutions futures
- Distinguez des autres erreurs : gérez uniquement le 404 ; les autres erreurs peuvent nécessiter un traitement différent
Vérification
- Simulez une perte de données du service externe (ou videz sa base de données)
- Lancez le script avec un cache local obsolète
- Devrait afficher le message « recreating », pas une panne avec 401/404
- Nouvelles valeurs en cache et utilisées pour les opérations ultérieures
- Script se termine avec succès
Exemple
Application du monde réel - Récupération du cache pubkey Keycast :
const cached = await pgDb.getImportedUser(creator.user_id);
let pubkey: string;
let token: string;
if (cached) {
pubkey = cached.pubkey;
token = cached.token;
try {
const freshToken = await keycast.getTokenByPubkey(pubkey);
token = freshToken;
await pgDb.saveImportedUser({ ...cached, token: freshToken });
console.log(`Pubkey: ${pubkey} (token refreshed)`);
} catch (refreshError) {
const errMsg = refreshError instanceof Error ? refreshError.message : String(refreshError);
if (errMsg.includes("not found")) {
// Keycast doesn't have this pubkey - cache is stale
console.log(`Cached pubkey not on Keycast, recreating user...`);
// Delete stale entry
await pgDb.deleteImportedUser(creator.user_id);
// Create fresh user
const result = await keycast.createPreloadedUser(
creator.user_id,
username,
displayName
);
pubkey = result.pubkey;
token = result.token;
console.log(`Pubkey: ${pubkey} (recreated)`);
// Cache new account
await pgDb.saveImportedUser({
vine_user_id: creator.user_id,
username: creator.username,
pubkey,
token,
events_published: 0,
});
} else {
// Other error - user may have claimed account, can't proceed
console.log(`Token refresh failed: ${errMsg}`);
console.log(`Skipping ${creator.username} - cannot sign events`);
continue;
}
}
}
Notes
- Ceci complète
local-cache-idempotency-fallback- utilisez les deux ensemble - La chaîne d'erreur trompeuse : 404 « not found » → continuer avec token obsolète → 401 « invalid token »
- Supprimez toujours avant de recréer pour éviter d'accumuler des entrées de cache orphelines
- Envisagez de logger les entrées qui étaient obsolètes pour le débogage/monitoring
- Si le service externe perd fréquemment des données, enquêtez sur la cause racine
- La nouvelle pubkey sera différente de l'ancienne - les systèmes aval peuvent nécessiter des mises à jour
Compétences Connexes
local-cache-idempotency-fallback: le motif de base que cette compétence étend- Logique de retry de base de données pour les réinitialisations de connexion (préoccupation distincte)