¿Hay alguna manera de enganchar la limpieza de caché?

16

Para un sitio web de una gran institución, con cachés pesados, me gustaría generar cachés lo antes posible, para que ningún usuario pueda llegar a la generación de caché ...

Tengo un cron configurado todos los minutos que lo hace, ejecutando algunas funciones y solicitando páginas críticas, pero lo que estoy buscando es una forma de saber cuándo se acaba de borrar el caché , preferiblemente un enlace, para que pueda iniciar esto funciones generadoras.

Alguna idea ?

Gregory Kapustin
fuente
Dependiendo de lo que intente lograr, la respuesta de phayes en la página es una buena solución para activar el código después de que se hayan borrado los cachés.
Lester Peabody

Respuestas:

7

No existe en Drupal 7.x, pero se agregó como un enlace central, hook_rebuild en Drupal 8.x después de que suficientes personas lo solicitaron. Sin embargo, puede haber una mejor manera de resolver su problema en 7.x: está intentando iniciar algún tipo de funcionalidad de calentamiento de caché justo después de que cron borre el caché, ¿correcto? Otra forma de abordar esto sería utilizar Elysia cron, que tiene una serie de mejoras significativas en el funcionamiento de cron, pero dos que podrían ser relevantes para su caso de uso son:

Elysia Cron extiende el cron estándar de Drupal, lo que permite un control de grano fino sobre cada tarea y varias formas de agregar trabajos cron personalizados a su sitio.

  • Establezca los tiempos y las frecuencias de cada tarea cron (puede ejecutar algunos trabajos todos los días a una hora específica, otros solo mensualmente, etc.). Para cada tarea, simplemente puede elegir entre algunas opciones de uso frecuente ("una vez al día", "una vez al mes" ...), o usar una sintaxis potente como "linux crontab" para establecer los tiempos precisos. Incluso puede definir sus opciones de uso frecuente para acelerar la configuración del sitio. ...
  • Cambiar la prioridad / orden de ejecución de la tarea. ...

Puede usar este módulo para tener un control más preciso sobre cómo se ejecuta su cron para ayudar a resolver el problema de la memoria caché obsoleta. Específicamente, puede agregar un enlace a sus funciones de reconstrucción para cron y luego usar Elysia cron, configurar estas operaciones para que se ejecuten inmediatamente después de la operación de borrado de caché.

También parece que puede tener problemas con la ejecución de cron para que el caché se vuelva a crear con demasiada frecuencia. Si ese es el caso, puede configurar la operación específica de borrado de caché en Elysia cron para que se ejecute a una velocidad diferente que el resto de sus operaciones cron, por lo que, por ejemplo, la indexación de búsqueda se actualizará cada 5 minutos, pero el borrado de caché completo solo se ejecutará cada 6 horas, etc.

Ajuste fino de la gestión de caché cron: drupal cron invalidará la memoria caché variable en cada ejecución cron, y este es un gran problema de rendimiento si tiene una tarea que se llama con frecuencia. Elysia cron optimiza la gestión de la memoria caché y no necesita invalidar la memoria caché.

schnippy
fuente
Bueno, esto es un verdadero fastidio. ¡Date prisa D8! En realidad, ya tengo, como te dije, un cron con elysia_cron, corriendo cada minuto, calentando lo que necesito. Pero como mi sitio va a tener> 10.000 / visitas / hora, estoy bastante seguro de que sbdy caerá en cachés vacíos ... Gracias de todos modos, ¡ahora sé que es una limitación D7!
Gregory Kapustin
12

La forma de hacerlo es usarlo hook_flush_cachesen combinación con register_shutdown_function. Código de ejemplo:

/**
 * 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
}

El uso register_shutdown_functionsignifica que se llamará a nuestra función de reconstrucción de caché después de que se hayan borrado los cachés. Abusamos hook_flush_cachesde una manera que nunca fue pensada para ser utilizada, pero esto debería hacer exactamente lo que necesita.

phayes
fuente
Realmente me gusta esta solución. Antes de usarlo, busqué cualquier problema / conflicto conocido que usara register_shutdown_function()en Drupal, y encontré drupal_register_shutdown_function () de Drupal core : "Contenedor para register_shutdown_function () que captura las excepciones lanzadas para evitar" Excepción lanzada sin un marco de pila en Desconocido " . sabe que le hace me siento mejor abusing hook_flush_cachessi estoy usando sólo las funciones del núcleo de Drupal para hacerlo.
runswithscissors
11

No, no hay Realmente no. Al menos no en 6 o 7. Suponiendo 7:

Si observas drupal_flush_all_caches(), verás que invoca hook_flush_caches(). Este gancho está destinado a:

"agregue nombres de tablas de caché a la lista de tablas de caché que se borrarán con el botón Borrar en la página Rendimiento o cada vez que se invoque drupal_flush_all_caches".

Sería tentador simplemente hacer que el gancho de su módulo dure y escribir código allí. Pero veamos de nuevo drupal_flush_all_caches(). La eliminación real ocurre así:

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

Significa que todos los ganchos se disparan antes de que algo se despeje realmente. Sólo hay una función llamada después de la eliminación real, _system_update_bootstrap_status()pero sólo llama hook_boot, hook_exit, hook_watchdogy hook_language_init- se engancha no desea poner en práctica sólo para proporcionar la funcionalidad de caché-claro-dependiente.

Mołot
fuente
Maldición, me tomó mucho tiempo agregar todos estos enlaces;) Lo dejaré por ahora ya que no puedo obligarme a eliminarlo, después de tanto tiempo dedicado a explicar por qué no se puede hacer.
Mołot
3
Déjalo, es una buena respuesta.
mpdonadio
Sí, déjalo, no puedo verificar todas las buenas respuestas, pero lo subí :)
Gregory Kapustin
8

Amplios trazos aquí:

Si bien no hay un gancho en la versión anterior a D8, podría escribir su propio backend de base de datos basado en el estándar DrupalDatabaseCachey luego escribir cualquiera o todo tipo de lógica en su clear()función. Una mirada rápida sugeriría que esto sea razonablemente sencillo en D7 (solo copie la clase a su nombre personalizado y modifíquelo, etc., agregando un, module_invoke_all()según corresponda) y con el módulo cache_backport incluso funcionaría en D6. A continuación, apunte los contenedores de caché que desee que estén fancified en clear y debería estar en camino.

Jimajamma
fuente
3
Esta es probablemente la mejor solución, el único 'problema' es que si tiene varios contenedores de caché (memcache, redis, etc.) debe extender varias clases de caché. Aún así vale la pena
Clive
No funcionaría con caché en memcached, apc u otra solución no db, ¿verdad?
Mołot
Yo uso Redis, no estoy seguro de que funcione.
Gregory Kapustin
Si está utilizando drupal.org/project/redis , debería poder simplemente copiar o modificar las clases proporcionadas, etc. en un módulo personalizado y luego usarlas en su lugar. Sin embargo, si está utilizando algo en la línea de la plataforma Pantheon donde proporcionan todo el trabajo pesado para redis, entonces sí, necesitaría coordinar con ellos sobre todo esto.
Jimajamma
3

Si observa la fuente para drupal_flush_all_caches()y clear_cache_all(), verá que no se invocan ganchos después de la limpieza, lo cual es un fastidio bastante molesto.

Es muy difícil garantizar que un usuario nunca tendrá que esperar a que se generen algunas entradas de caché, por lo que trato de evitar la eliminación de la memoria caché completa tanto como sea posible.

Un método que realmente ayuda es formar alterar la página de rendimiento para conectar un controlador de envío que simplemente borra los cachés orientados hacia adelante y no toca los menús, el registro y los cachés centrales similares. He tenido buenos resultados con esto, ya que la reconstrucción del menú y el registro ocupa aproximadamente la mitad del tiempo para una reconstrucción completa de la memoria caché.

La otra cosa es que tengo un script drush que hace un drupal_http_request()en todas mis URL (no solo las importantes) para que todo se almacene en caché. Cómo se hace esto varía según el sitio. A veces puedo simplemente EFQ los nodos publicados, y construir URL de esa manera. Otras veces, puede consultar las tablas del mapa del sitio XML para obtener su URL. Luego llamo a esto desde mi cron del sistema con la frecuencia que necesito.

mpdonadio
fuente
1

Un par de opciones:
https://www.drupal.org/project/cache_graceful podría ser exactamente lo que quieres.

https://www.drupal.org/project/apdqc tiene 2 ganchos que se activan en una memoria caché que le permite alterar la limpieza drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);y luego le permite reaccionar a la limpieza module_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);. Haga que APDQC funcione correctamente y configúrelo $conf['apdqc_call_hook_on_clear'] = TRUE;en su archivo settings.php y luego se debe llamar a los ganchos cada vez que se realiza un borrado de caché.

mikeytown2
fuente
1

Es posible que esto no sea adecuado para todos y que no sea lo suficientemente rápido para el OP, ya que solo se activa en la inicialización de la página siguiente. Sin embargo, me ayudó a activar el código justo después de un "borrar todo el caché" que no era sensible al tiempo.

Obviamente, HOOKdebe reemplazarse con el nombre de su propio módulo.

/**
 * 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.
}

Si tiene un contenedor específico al que debe apuntar, lo anterior podría modificarse para admitirlo, siempre que el contenedor completo se vacíe en el punto de su caché libre.

hook_initsolo se ejecuta para páginas no almacenadas en caché. Aunque debido a que un borrado de caché completo debería significar que no hay páginas en caché, esto no debería causar un problema. Sin embargo, los sistemas de almacenamiento en caché externos como Varnish se interpondrán en el camino de esta activación y significarán que solo ocurrirá cuando la próxima solicitud adecuada llegue a Drupal.

También debe tenerse en cuenta que, dependiendo de su sistema de almacenamiento en caché, exactamente cuando cache_setesté disponible para todos los usuarios concurrentes, este enganche podría activarse varias veces al mismo tiempo, especialmente si tiene un gran número de usuarios.

Pebbl
fuente
0

Tenía una necesidad similar, donde un cliente quería limpiar las cachés de Drupal y Varnish cuando pulsaba el botón "vaciar todas las cachés". Secuestré ese elemento del menú para hacerlo.

Esto no afectará a ningún borrado de caché en cron o en cualquier otro lugar, solo en el enlace del menú.

/**
 * 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
}
Travis Lilleberg
fuente
Thx Travis, pero estoy buscando una forma que se enganche en cualquier almacenamiento en caché claro, no solo el que se activa voluntariamente por un usuario.
Gregory Kapustin
0

Puede probar https://www.drupal.org/project/recacher : utiliza el módulo de caducidad de caché para detectar páginas caducadas y luego vuelve a almacenar en caché solo esas páginas con el excelente HTTPRL.

Vacilando
fuente