API per creazione cataloghi PDF

API per creazione cataloghi PDF

Cliente: Silca
Framework php: Laravel + TCPDF
Altre attività: Configurazione della macchina virtuale che ospita i servizi
Risultato chiave: Creazione dinamica dei cataloghi PDF e ottimizzazione dei tempi di elaborazione

Richiesta del cliente

Realizzazione di un servizio indipendente che riceve un elenco di chiavi e produce diversi tipi di catalogo PDF.

Realizzazione

Avevo già sviluppato per l'azienda una serie di "cataloghi automatici"; i cataloghi richiesti erano, in pratica, molto simili ad alcuni che avevo già realizzato. La differenza sostanziale è che in precedenza la generazione dei cataloghi si basava su dati e immagini locali, presenti nella piattaforma che avevo realizzato e gestivo (The Catalogue), mentre il servizio per la nuova piattaforma MYKEYS Pro avrebbe dovuto ricevere un semplice elenco preimpostato di informazioni, oltre agli indirizzi delle immagini da impaginare.

L'azienda mi ha fornito una VM basata su Linux, con accesso ssh tramite VPN. Ho installato e configurato i pacchetti necessari, in questo caso fondamentalmente php e il server web.

L'impaginazione dei cataloghi è realizzata con la libreria TCPDF.

Il servizio, dopo l'autenticazione, espone diversi endpoint per produrre cataloghi e fogli di etichette di vario tipo. La prima sezione del file JSON ricevuto indica i parametri di impaginazione; la seconda riporta l'elenco delle chiavi, con una serie di informazioni opzionali e gli indirizzi delle immagini.

Il problema dei 100 secondi

Qualche tempo dopo la pubblicazione in produzione, vengo avvisato che in alcuni casi il servizio andava in timeout, senza quindi produrre alcun PDF. I PDF con poche chiavi non presentavano il problema, mentre i cataloghi più corposi avevano tempi di elaborazione piuttosto lunghi, e a volte non venivano prodotti.

Avevo già aumentato i tempi di elaborazione degli script di PHP oltre il tempo di default; in locale tutti i cataloghi venivano prodotti correttamente, quindi ho escluso un problema di formattazione del file JSON, com'era già capitato in precedenza.

Ho iniziato a cronometrare le richieste sul server di produzione, e quelle che non venivano portate a termine si fermavano sempre a un minuto e 40 secondi. Avevo trovato una costante: il tempo di elaborazione. Non riuscivo però a capire dove fosse impostato questo limite: sicuramente non sulla "mia" VM. Un minuto e 40" sono 100 secondi: una ricerca in rete mi ha fatto capire che questo è il limite di timeout imposto da Cloudflare su tutti i piani tranne quello Enterprise.

Trovato il problema, era necessario pensare a una soluzione.

Velocità

L'azienda non era molto favorevole a passare dal piano Business a quello Enterprise di Cloudflare solo per risolvere un problema di tempi di elaborazione, che imputavano al mio servizio. Perciò ho iniziato a ragionare su come eliminare i colli di bottiglia: il tempo di elaborazione maggiore era, secondo i miei test, il recupero delle immagini da un altro server, per cui ho proposto lo sviluppo di una cache locale delle immagini.

Il responsabile tecnico del progetto non era d'accordo: secondo lui il passaggio dei file tra i due server, essendo sullo stesso tenant di Azure, non poteva essere lento. Visti i lunghi tempi di elaborazione, il responsabile proponeva l'implementazione di una coda di stampa sul server e una serie di nuove API, ad esempio per indicare lo stato dell'elaborazione, oltre a nuove API nella piattaforma per ricevere notifica dei PDF conclusi. La piattaforma avrebbe avvisato l'utente finale sulla disponibilità del catalogo.

Allora ho dovuto giocare un po' d'azzardo: ho deciso di implementare il sistema di caching locale delle immagini, anche se la soluzione non era stata approvata.

Con l'attivazione della cache, il file con 800 chiavi che in produzione andava in timeout dopo 10 minuti, senza essere concluso, veniva prodotto in 4 secondi; quattro richieste contemporanee di un catalogo con 2400 chiavi venivano soddisfatte in meno di un minuto.

Problema risolto, cache approvata.

Ho chiesto copia di tutte le immagini per salvarle nello storage locale, e ho creato un solo nuovo endpoint per eliminare una chiave dalla cache. Le nuove chiavi vengono aggiunte alla cache alla prima richiesta.

Ho eseguito anche un test preliminare utilizzando Redis, e i tempi sono ancora più brevi; per il carico di lavoro attuale, il cliente ha ritenuto sufficiente la cache su file.

P.S.: non è vero che "il cliente ha sempre ragione" :-)

© 2025 Giacomo Vernoni
P. IVA 02995030307
Facebook·Linkedin