Il catalogo che si ricostruiva per nessuno
Ogni volta che un visitatore anonimo apriva il catalogo di una biblioteca su Pinakes, il software rifaceva la pagina da zero. Le stesse giunzioni su autori, editori e collane, gli stessi conteggi delle sfaccettature, le stesse recensioni: tutto ricalcolato, a ogni singola visita. Il punto è che quel lavoro è identico per ogni visitatore anonimo tra due modifiche del catalogo, eppure girava di nuovo ogni volta. Per una biblioteca pubblica con un po’ di traffico significa una montagna di query inutili e pagine più lente per chi cerca un libro.
La 0.7.71 è la release che smette di farlo. Le pagine che vede il pubblico — la home, il catalogo e i risultati di ricerca, la scheda di ogni libro — ora sono servite dalla cache invece di essere ricostruite a ogni richiesta. E su un server LiteSpeed possono essere servite senza eseguire una riga di PHP.
L’overhaul, a strati
Non è arrivato tutto insieme, ed è stato deliberato: ogni pezzo è sicuro da solo. Prima una query cache con invalidazione a costo costante — Pinakes tiene in cache i dati costosi (la scheda libro, il blocco recensioni, gli elenchi di catalogo e ricerca) per lingua, e quando qualcosa cambia non scansiona e non cancella niente: incrementa un contatore di generazione e tutte le voci precedenti diventano irraggiungibili in un colpo solo. I contatori si scrivono in modo atomico, così una scrittura fallita non può mai riesumare dati vecchi.
Poi la materializzazione: i conteggi del catalogo, le sfaccettature e l’autore principale di ogni libro non si ricalcolano più con sottoquery correlate a ogni pagina, ma si mantengono nel database. Se per qualsiasi motivo non sono disponibili, Pinakes torna semplicemente alla query dal vivo. Niente si rompe, si degrada.
L’edge cache LiteSpeed: la promessa e la trappola
Il pezzo grosso è la cache full-page di LiteSpeed, opzionale. Su LiteSpeed o OpenLiteSpeed puoi accenderla da Impostazioni → Avanzate: le pagine anonime di home, catalogo e libro vengono servite direttamente dal web server, senza PHP a ogni hit, con durate indipendenti per tipo di pagina e uno svuotamento con un clic.
Qui c’è stata la lezione più istruttiva. Nelle prime versioni l’interruttore c’era, si accendeva, si salvava — e non cachava niente. Il server ignorava tutto perché mancava una direttiva, CacheLookup on, che dice a LiteSpeed di guardare davvero nella cache. Pinakes scriveva le regole di privacy nel file .htaccess ma non quella riga, e senza quella riga il resto è decorazione. Un interruttore che si accende e non fa niente è peggio di un interruttore assente: quello assente almeno è onesto. Ora la direttiva viene scritta quando serve, e un aggiornamento ripara da solo un’installazione che aveva il blocco vecchio, così l’interruttore non è mai inerte.
Stessa filosofia altrove: se il tuo server non è LiteSpeed — e l’immagine Docker ufficiale, che gira su Apache, non lo è mai — la sezione della cache LiteSpeed semplicemente non compare. Non ha senso mostrarti un controllo per una cache che il tuo server non può usare.
La disponibilità non si mette mai in cache
È la garanzia che ha reso l’intera cosa spedibile. La disponibilità delle copie — quante sono libere, se un libro si può prendere in prestito adesso — viene tolta da ogni payload in cache e riletta dal vivo a ogni richiesta. L’HTML in cache porta l’impaginazione e i metadati del libro; i numeri veri vengono riempiti dopo il rendering, attraverso un piccolo endpoint no-store. Così anche su una pagina servita interamente dall’edge cache il lettore vede sempre la disponibilità reale e aggiornata, e i pulsanti per prendere in prestito o prenotare sono sempre live.
E la cache è prudente per default: utenti autenticati, modalità privata, qualsiasi cosa con un cookie di sessione, gli invii dei form e ogni pagina che il codice non ha marcato esplicitamente come cacheabile passano oltre e ricevono una risposta normale, non in cache.
I numeri
Misurati su un’installazione LiteSpeed reale (una biblioteca di documentazione), pagine anonime, mediana su dodici richieste ciascuna:
- Home: da 231 ms a circa 106 ms (TTFB ~45 ms)
- Catalogo: da 252 ms a circa 107 ms (TTFB ~45 ms)
- Scheda libro: da 242 ms a circa 105 ms (TTFB ~45 ms)
Con l’edge cache accesa il tempo al primo byte scende da circa 115 ms a circa 45 ms — e gran parte di quel che resta è pura latenza di rete, perché su quegli hit il server non esegue PHP affatto. Come contorno, il CSS e il JavaScript del lettore di audiolibri ora si caricano solo sulle pagine che un audiolibro ce l’hanno davvero, e i font delle icone non bloccano più il primo disegno della pagina.
Aggiornare
Niente da fare oltre l’aggiornamento consueto. Nessuna modifica che rompe, nessuna nuova dipendenza obbligatoria. Le installazioni esistenti ricevono una piccola migrazione di materializzazione del catalogo, idempotente, che gira da sola (l’updater interno fa comunque il backup del database, come sempre). Il supporto a Redis per la coerenza tra più server è lasciato di proposito a una release futura.
Buon catalogo veloce. Pinakes 0.7.71 su GitHub.
