C'è un modo per agganciare la cancellazione della cache?


16

Per un sito Web di grandi istituzioni, con cache pesanti, vorrei generare cache il più presto possibile, in modo che nessun utente possa arrivare sulla generazione della cache ...

Ho un cron set di tutti i minuti che lo fa, eseguendo alcune funzioni e richiedendo pagine critiche, ma quello che sto cercando è un modo per sapere quando la cache è stata appena cancellata , preferibilmente un hook, quindi posso lanciare questo generatrici funzioni.

Qualche idea ?


A seconda di ciò che stai cercando di realizzare, la risposta di phayes in fondo alla pagina è una buona soluzione per attivare il codice dopo che le cache sono state cancellate.
Lester Peabody,

Risposte:


7

Non c'è Drupal 7.x ma questo è stato aggiunto come hook core, hook_rebuild in Drupal 8.x dopo che abbastanza persone lo hanno richiesto. Tuttavia, potrebbe esserci un modo migliore per risolvere il problema in 7.x: stai cercando di avviare una sorta di funzionalità di riscaldamento della cache subito dopo che cron cancella la cache, giusto? Un altro modo per affrontare questo sarebbe usare Elysia cron che ha una serie di miglioramenti significativi al funzionamento di cron ma due che potrebbero essere rilevanti per il tuo caso d'uso sono:

Elysia Cron estende il cron standard di Drupal, consentendo un controllo accurato di ogni attività e diversi modi per aggiungere lavori cron personalizzati al tuo sito.

  • Imposta i tempi e le frequenze di ciascuna attività cron (puoi eseguire alcuni lavori ogni giorno a un'ora specificata, altri solo mensilmente e così via ...). Per ogni attività puoi semplicemente scegliere tra alcune opzioni usate di frequente ("una volta al giorno", "una volta al mese" ...), oppure usare una potente sintassi simile a "linux crontab" per impostare i tempi precisi. È anche possibile definire le opzioni utilizzate di frequente per accelerare la configurazione del sito. ...
  • Modifica la priorità / l'ordine di esecuzione dell'attività. ...

Puoi usare questo modulo per avere un controllo più preciso su come viene eseguito cron per aiutarti a risolvere il problema della cache non aggiornato. In particolare, è possibile aggiungere un gancio alle funzioni di ricostruzione su cron e quindi utilizzando Elysia cron, impostare queste operazioni in modo che vengano eseguite immediatamente dopo l'operazione di svuotamento della cache.

Sembra anche che potresti avere problemi con cron in esecuzione che porta spesso a ricreare la cache troppo spesso. In tal caso, puoi impostare l'operazione di svuotamento della cache specifica in Elysia cron in modo che venga eseguita a una velocità diversa rispetto al resto delle tue operazioni cron, quindi ad esempio l'indicizzazione della ricerca si aggiornerà ogni 5 minuti ma l'intera svuotamento della cache eseguirà solo ogni 6 ore, ecc.

Ottimizza la gestione della cache cron: drupal cron invaliderà la cache variabile ad ogni esecuzione cron e questo è un grande problema di prestazioni se hai un'attività chiamata di frequente. Elysia cron ottimizza la gestione della cache e non ha bisogno di invalidare la cache.


Bene, questo è un vero peccato. Sbrigati D8! In realtà, come ho detto, l'alreadry ha un cron con elysia_cron, che corre ogni minuto, riscaldando ciò di cui ho bisogno. Ma dato che il mio sito avrà> 10.000 / visite / ora, sono abbastanza sicuro che sbdy cadrà in cache vuote ... Grazie comunque, ora so che è un limite D7!
Gregory Kapustin,

12

Il modo per farlo è usare hook_flush_cachesin combinazione con register_shutdown_function. Codice di esempio:

/**
 * Implements hook_flush_caches().
 */
function mymodule_flush_caches() {
   // After caches are cleared we will run mymodule_cache_rebuild()
   register_shutdown_function('mymodule_cache_rebuild');

   // We don't want to add any custom cache-tables, so just return an empty array
   return array();
}

/**
 * Rebuild expensive cache items that need to be rebuilt immediately.
 */
function mymodule_cache_rebuild() {
  // Do the cache rebuild work here
}

Utilizzo register_shutdown_functionsignifica che la nostra funzione di ricostruzione della cache verrà chiamata dopo che le cache sono state cancellate. Stiamo abusando hook_flush_cachesin un modo che non è mai stato progettato per essere utilizzato, ma questo dovrebbe fare esattamente ciò di cui hai bisogno.


Mi piace molto questa soluzione. Prima di usarlo da solo, ho cercato eventuali problemi / conflitti noti usando register_shutdown_function()in Drupal, e mi sono imbattuto in drupal_register_shutdown_function () di Drupal core : "Wrapper for register_shutdown_function () che rileva eccezioni generate per evitare" Eccezione generata senza una cornice di stack in Sconosciuto " . so che mi fa sentire meglio abusing hook_flush_cachesse sto usando solo le funzioni principali di Drupal per farlo.
corsa con le forbici

11

No, non c'è. Non proprio. Almeno non in 6 o 7. Supponendo 7:

Se guarderai drupal_flush_all_caches()vedrai che invoca hook_flush_caches(). Questo hook ha lo scopo di:

"aggiungi i nomi delle tabelle della cache all'elenco delle tabelle della cache che verranno cancellate dal pulsante Cancella nella pagina Prestazioni o ogni volta che viene invocato drupal_flush_all_caches."

Sarebbe tentato semplicemente di far durare l'hook del tuo modulo e scrivere il codice lì. Ma guardiamo di nuovo drupal_flush_all_caches(). La cancellazione effettiva avviene in questo modo:

  $cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
  foreach ($cache_tables as $table) {
    cache_clear_all('*', $table, TRUE);
  }

Significa che tutti i ganci vengono lanciati prima che qualcosa venga veramente cancellato. C'è solo una funzione chiamata dopo la cancellazione vera e propria, _system_update_bootstrap_status()ma solo chiamate hook_boot, hook_exit, hook_watchdoge hook_language_init- ganci non si vuole implementare solo per fornire funzionalità di cache-chiara-dipendente.


Accidenti, mi ci è voluto molto per aggiungere tutti questi collegamenti;) Per ora lo lascerò perché non posso costringermi ad eliminarlo, dopo tanto tempo speso a spiegare perché non è possibile farlo.
Mołot,

3
Lascialo, è una buona risposta.
mpdonadio

Sì, lascialo, non riesco a controllare tutte le risposte valide ma l'ho aumentato :)
Gregory Kapustin,

8

Grandi tratti qui:

Sebbene non sia presente un hook in pre-D8, è possibile scrivere il proprio back-end del database in base a quello standard DrupalDatabaseCachee quindi scrivere qualsiasi o tutti i tipi di logica nella propria clear()funzione. Una rapida occhiata suggerirebbe che ciò sia ragionevolmente semplice in D7 (basta copiare la classe sul tuo nome personalizzato e modificarla ecc. Inserendo un module_invoke_all()come appropriato) e con il modulo cache_backport funzionerebbe anche in D6. Quindi, deseleziona tutti i contenitori della cache che desideri fancificare e dovresti essere sulla buona strada.


3
Questa è probabilmente la soluzione migliore, il solo "problema" è che se hai più bin della cache (memcache, redis, ecc.) Devi estendere diverse classi di cache. Ne vale comunque la pena
Clive

Non funzionerebbe con la cache in memcached, apc o altra soluzione non-db, vero?
Mołot,

Uso Redis, non sono sicuro che funzionerebbe.
Gregory Kapustin,

Se stai usando drupal.org/project/redis dovresti essere in grado di copiare o modificare in altro modo le classi fornite ecc. In un modulo personalizzato e quindi usarle. Se, tuttavia, stai usando qualcosa lungo le linee della piattaforma Pantheon dove forniscono tutto il sollevamento pesante per i redis, allora sì, dovresti coordinarti con loro su tutto questo.
Jimajamma

3

Se guardi la fonte per drupal_flush_all_caches()e clear_cache_all(), vedrai che nessun hook viene invocato dopo la cancellazione, il che è un bel bummer.

È molto difficile garantire che un utente non debba mai attendere la creazione di alcune voci della cache, quindi cerco di evitare il più possibile le cancellazioni complete della cache.

Un metodo che aiuta davvero è quello di modificare la pagina delle prestazioni per collegare un gestore di invio che cancella solo le cache rivolte in avanti e non tocchi i menu, il registro e le cache core simili. Ho avuto buoni risultati con questo, poiché la ricostruzione del menu e del registro impiega circa la metà del tempo per una ricostruzione completa della cache.

L'altra cosa che ho un drush script che fa un drupal_http_request() su tutti i miei URL (non solo quelli importanti) in modo che tutto venga memorizzato nella cache. Il modo in cui ciò avviene varia in base al sito. A volte posso solo EFQ i nodi pubblicati e creare URL in quel modo. Altre volte, è possibile eseguire una query nelle tabelle Sitemap XML per ottenere l'URL. Quindi lo chiamo dal mio cron di sistema tutte le volte che ho bisogno.


1

Coppia di opzioni:
https://www.drupal.org/project/cache_graceful potrebbe essere esattamente quello che vuoi.

https://www.drupal.org/project/apdqc ha 2 hook che si attivano in una cache cancellata permettendoti di modificare la cancellazione drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);e dopo averti permesso di reagire alla cancellazione module_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);. Fai funzionare correttamente APDQC e impostalo $conf['apdqc_call_hook_on_clear'] = TRUE;nel tuo file settings.php e quindi gli hook dovrebbero essere chiamati ogni volta che viene eseguita la cancellazione della cache.


1

Questo potrebbe non essere adatto a tutti e potrebbe non essere abbastanza veloce per l'OP, poiché viene attivato solo alla pagina iniziale. Tuttavia, mi ha aiutato con l'attivazione del codice subito dopo una "cache clear all" che non era sensibile al tempo.

Ovviamente HOOKdeve essere sostituito con il proprio nome del modulo.

/**
 * Implements hook_init().
 */
function HOOK_init(){
  // if there is no cache_not_empty defined, define it 
  // and then trigger our cache cleared code
  if ( !cache_get('HOOK_cache_not_empty') ) {
    cache_set('HOOK_cache_not_empty', TRUE);
    foreach (module_implements('cache_cleared') as $module) {
      module_invoke($module, 'cache_cleared');
    }
  }
}

/**
 * Implements hook_cache_cleared().
 */
function HOOK_cache_cleared(){
  // do what you need here, in which ever module.
}

Se si dispone di un contenitore specifico che è necessario targetizzare, quanto sopra potrebbe essere modificato per supportarlo, purché l'intero contenitore venga svuotato nel punto in cui la cache viene svuotata.

hook_initviene eseguito solo per pagine non memorizzate nella cache. Anche se a causa di una cancellazione completa della cache non devono essere presenti pagine memorizzate nella cache, ciò non dovrebbe causare problemi. Tuttavia, i sistemi di cache esterni come Varnish ostacoleranno questo innesco e significheranno che accadrà solo quando la successiva richiesta corretta tornerà a Drupal.

Va inoltre notato che a seconda del sistema di memorizzazione nella cache - esattamente quando cache_setdiventa disponibile per tutti gli utenti simultanei - che questo hook potrebbe essere attivato più volte contemporaneamente, specialmente se si dispone di un numero elevato di utenti.


0

Avevo un'esigenza simile, in cui un cliente voleva svuotare le cache Drupal e Varnish quando premeva il pulsante "Svuota tutte le cache". Ho dirottato quella voce di menu per farlo.

Questo non colpirà alcuna cancellazione della cache su cron o altrove - solo sul collegamento del menu.

/**
 * Implements hook_menu_alter().
 */
function mymodule_menu_alter(&$items) {
  if (isset($items['admin_menu/flush-cache'])) {
    $items['admin_menu/flush-cache']['page callback'] =
      "_mymodule_custom_flush_cache";
  }
}

/**
 * Hijacks the "flush all caches" button in menu
 */
function _mymodule_custom_flush_cache() {
  /**
   * Clear varnish, or other logic here
   */
  admin_menu_flush_cache(); //Run the normal cache clearing stuff
}

Grazie Travis, ma sto cercando un modo per agganciare l'eventuale memorizzazione nella cache, non solo quello attivato volontariamente da un utente.
Gregory Kapustin,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.