Ho notato che il task rake assets:precompile richiede una connessione al database: ciò significa che il task può essere eseguito solo in fase di “esecuzione” (dopo il deployment) e non in fase di “build” (durante la costruzione dell’immagine del container). Dato che il task è molto costoso in termini di tempo di esecuzione, questo può risultare fastidioso.
Non essendo uno sviluppatore Ruby/Rails, ho fatto alcune ricerche e ho scoperto che questo comportamento poteva essere disabilitato fino a Rails 4; successivamente, gli sviluppatori hanno fatto ricorso a degli “hack” (connessione al database nulla). Quest’ultimo approccio richiede ovviamente una conoscenza approfondita dell’applicazione per evitare di rompere qualcosa.
Mentre cercavo una soluzione migliore, ho trovato questo commit che sembra simile nello spirito. Le mie domande sono quindi:
gli sviluppatori stanno già lavorando alla questione, o ci sono motivi tecnici per cui non è possibile farlo?
se alcune parti del task richiedono effettivamente la connessione al database, sarebbe fattibile dividere il task in due (o più) parti, in modo che alcune operazioni (ad esempio la compilazione delle localizzazioni, la minificazione di JS e CSS) possano essere eseguite in fase di build?
esiste al momento un workaround noto (ad esempio “database nullo” come menzionato sopra)?
I temi sono archiviati nel database (vengono modificati nell’interfaccia di amministrazione), quindi il CSS si trova all’interno di PostgreSQL. Di conseguenza, è necessaria la connessione al database al momento della build per poterli precompilare.
Sarebbe possibile implementare la compilazione delle localizzazioni separatamente (da eseguire al momento della build)?
Inoltre, immagino che alcuni ambienti (nel mio caso almeno) potrebbero non voler permettere la modifica dei temi: sarebbe possibile fornire un’alternativa di archiviazione per il CSS in questo caso?
Abbiamo discusso l’idea di un interruttore che disabilitasse l’intera interfaccia di personalizzazione, consentendo la compilazione dei file CSS al momento della build e il caricamento nell’archiviazione oggetti durante la build (ovvero, come avviene per il core JS e i plugin).
Tuttavia, si tratta di un caso molto di nicchia, che potrebbe interessare solo implementazioni di tipo aziendale, senza offrire alcun valore al 99% delle comunità presenti sul web. Di conseguenza, non è prevista nella nostra roadmap e sarebbe molto difficile giustificare l’impegno di risorse per questo lavoro rispetto allo sviluppo di nuove funzionalità o al miglioramento delle prestazioni.
Puoi fornirci maggiori dettagli sul tuo ambiente e sul caso d’uso?
Bene sapere che l’idea è già stata discussa. Capisco che il lavoro necessario per il cambiamento sia probabilmente troppo grande per essere giustificato.
Nel mio caso, Discourse sarà associato a un sito web preesistente, quindi ci sarà un tema personalizzato fisso per abbinarlo a quello del sito: non avrebbe senso cambiarlo dinamicamente.
Oh: beh, quando costruisco l’immagine, lavoro sul mio portatile di sviluppo. L’immagine viene poi caricata su un repository, e il sistema finale (VPS su DigitalOcean) la recupera da lì.
Il database risiede in un volume sul VPS, quindi non può essere aggiornato dal mio portatile: ciò richiederebbe di fermare Discourse, sincronizzare il database sul mio portatile tramite rsync, costruire e caricare l’immagine, e infine riavviare Discourse…
Quindi stai eseguendo il database e l’applicazione all’interno dello stesso droplet?
In tal caso, attenendoti alla nostra guida ufficiale di installazione, che porta a un droplet con applicazione e database nello stesso droplet, otterrai un sito completamente funzionante, aggiornabile dall’interfaccia web e opzionalmente dalla riga di comando con una ricostruzione completa dell’immagine.
Se con questo intendi “direttamente sull’host”, allora no. Sono in esecuzione in un container, in particolare un container podman. Idealmente, dividerei il container in più container (uno per Discourse, uno per PostgreSQL, uno per Redis…), ma questo si collega alla questione che stiamo discutendo, quindi sono ancora incerto sulla strada migliore da percorrere.
Mi sembra poco sicuro. In genere eseguo i test dei container nel mio ambiente di sviluppo prima di distribuirli in produzione. Inoltre, idealmente i container dovrebbero essere in sola lettura.
Puoi dividere questi container e poi eseguire il processo di avvio dell’immagine in un’altra istanza (droplet) di breve durata. Poiché le istanze vengono addebitate a ore, questo sarà economico. Puoi anche sfruttare la rete privata tra l’host del container del database e l’host del container di “build”.
Ehi, grazie per l’idea, ma diventa complicato. Inoltre, non risolverebbe il problema, perché dovremmo comunque fermare Discourse e attendere il processo di bootstrap, altrimenti potrebbero esserci dati inconsistenti.
Sembra che dovremo accettare un lungo tempo di inattività (5-6 minuti per la migrazione e la precompilazione) durante gli aggiornamenti. Tuttavia, apprezzerei se poteste mantenere un issue a bassa priorità nel tracker, magari con un link a questo argomento.
Bene, grazie. In questo caso, dividerò sicuramente i container, che è un’architettura migliore in ogni caso.
Tuttavia, non riesco a capire quale differenza faccia? Se non sbaglio, tutti i container condividono tutte le CPU dell’host (a meno che non sia configurato diversamente), quindi i processi dovrebbero essere eseguiti in parallelo in entrambi i casi. Mi sto perdendo qualcosa?
Il tuo vecchio container rimarrà in esecuzione mentre quello nuovo viene avviato. Potrai quindi disattivare rapidamente quello vecchio e avviare quello nuovo, riducendo così i tempi di inattività.