Existe uma maneira de ligar a limpeza de cache?

16

Para um site de grande instituição, com caches pesados, eu gostaria de gerar caches o mais rápido possível, para que nenhum usuário possa chegar na geração de cache ...

Eu tenho um cron definido todos os minutos para isso, executando algumas funções e solicitando páginas críticas, mas o que estou procurando é uma maneira de saber quando o cache acabou de ser limpo , de preferência um gancho, para que eu possa iniciar isso. funções geradoras.

Qualquer ideia ?

Gregory Kapustin
fonte
Dependendo do que você está tentando realizar, a resposta do phayes na página é uma boa solução para disparar o código após a limpeza dos caches.
Lester Peabody

Respostas:

7

Não existe no Drupal 7.x, mas isso foi adicionado como um gancho central, hook_rebuild no Drupal 8.x, depois que um número suficiente de pessoas solicitou. Porém, pode haver uma maneira melhor de resolver seu problema no 7.x - você está tentando iniciar algum tipo de funcionalidade de aquecimento do cache logo após o cron limpar o cache, correto? Outra maneira de abordar isso seria usar o Elysia cron, que possui várias melhorias significativas na forma como o cron opera, mas duas que podem ser relevantes para o seu caso de uso são:

O Elysia Cron estende o cron padrão do Drupal, permitindo um controle de granulação fina sobre cada tarefa e várias maneiras de adicionar tarefas cron personalizadas ao seu site.

  • Defina os horários e as frequências de cada tarefa cron (você pode executar alguns trabalhos todos os dias em uma hora especificada, outros apenas mensalmente e assim por diante ...). Para cada tarefa, você pode simplesmente escolher entre algumas opções usadas com freqüência ("uma vez por dia", "uma vez por mês" ...) ou usar uma poderosa sintaxe semelhante ao "linux crontab" para definir os horários precisos. Você pode até definir suas opções usadas com frequência para acelerar a configuração do site. ...
  • Mude a prioridade / ordem da execução da tarefa. ...

Você pode usar este módulo para ter um controle mais refinado sobre como o cron é executado para ajudar a resolver o problema de cache obsoleto. Especificamente, você pode adicionar um gancho às funções de reconstrução do cron e, em seguida, usando o Elysia cron, defina essas operações para serem executadas imediatamente após a operação de limpeza de cache.

Também parece que você pode estar tendo problemas com o cron em execução, o que frequentemente leva à recriação do cache com muita frequência. Se for esse o caso, você pode definir a operação específica de limpeza de cache no Elysia cron para ser executada em uma taxa diferente do restante das operações cron, portanto, por exemplo, a indexação da pesquisa será atualizada a cada 5 minutos, mas a limpeza completa do cache será executada apenas a cada 6 horas, etc.

Ajuste o gerenciamento de cache do cron: o drupal cron invalidará o cache variável a cada execução do cron, e esse é um grande problema de desempenho se você tiver uma tarefa chamada com freqüência. O cron Elysia otimiza o gerenciamento de cache e não precisa invalidar o cache.

schnippy
fonte
Bem, isso é realmente uma chatice. Depressa, D8! Na verdade, eu já tenho, como eu disse, um cron com elysia_cron, funcionando a cada minuto, aquecendo o que eu preciso. Mas como meu site terá> 10.000 / visitas / hora, tenho certeza de que o sbdy cairá em caches vazios ... De qualquer forma, sei agora que é uma limitação do D7!
Gregory Kapustin
11

Não, não existe. Na verdade não. Pelo menos não em 6 ou 7. Supondo 7:

Se você olhar drupal_flush_all_caches(), verá que ele chama hook_flush_caches(). Este gancho é destinado a:

"adicione nomes de tabelas de cache à lista de tabelas de cache que serão limpas pelo botão Limpar na página Desempenho ou sempre que invocar drupal_flush_all_caches."

Seria tentador simplesmente fazer o gancho do seu módulo durar e escrever o código lá. Mas vamos olhar novamente drupal_flush_all_caches(). A exclusão real ocorre assim:

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

Isso significa que todos os ganchos são disparados antes que algo seja realmente limpo. Há apenas uma função chamada após a exclusão real, _system_update_bootstrap_status()mas ele só chama hook_boot, hook_exit, hook_watchdoge hook_language_init- conecta você não deseja implementar apenas para fornecer a funcionalidade de cache-claro-dependente.

Mołot
fonte
Droga, demorei muito tempo a adicionar todos esses links;) Vou deixar por enquanto, pois não posso me forçar a excluí-lo, depois de tanto tempo explicando por que isso não pode ser feito.
Mołot 02/09
3
Deixa, é uma boa resposta.
mpdonadio
Sim deixá-lo, eu não posso verificar todas as boas respostas, mas eu levantei-lo :)
Gregory Kapustin
11

A maneira de fazer isso é usar hook_flush_cachesem combinação com register_shutdown_function. Código de exemplo:

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

Usar register_shutdown_functionsignifica que nossa função de reconstrução de cache será chamada após a limpeza dos caches. Estamos abusando hook_flush_cachesde uma maneira que nunca foi planejada para ser usada, mas isso deve fazer exatamente o que você precisa.

phayes
fonte
8

Traços gerais aqui:

Embora não exista um gancho disponível no pré-D8, você pode escrever seu próprio back-end do banco de dados com base no padrão DrupalDatabaseCachee, em seguida, gravar todo ou qualquer tipo de lógica em sua clear()função. Uma rápida olhada sugeriria que isso é razoavelmente simples no D7 (basta copiar a classe para o seu nome personalizado e modificá-lo etc., lançando um module_invoke_all()conforme apropriado) e com o módulo cache_backport funcionaria no D6. Em seguida, aponte as caixas de cache que você deseja que fiquem claras e você deve estar a caminho.

Jimajamma
fonte
3
Esta é provavelmente a melhor solução, apenas o "problema" é que, se você tiver várias caixas de cache (memcache, redis, etc), precisará estender várias classes de cache. Ainda vale a pena embora
Clive
Não funcionaria com cache em memcached, apc ou outra solução não db, funcionaria?
Mołot
Eu uso Redis, não tenho certeza se funcionaria.
precisa saber é o seguinte
Se você estiver usando drupal.org/project/redis , poderá copiar ou modificar as classes fornecidas, etc. em um módulo personalizado, e depois usá-las. Se, no entanto, você estiver usando algo ao longo das linhas da plataforma Pantheon, onde eles fornecem todo o trabalho pesado para redis, então sim, você precisará se coordenar com eles sobre tudo isso.
Jimajamma #
3

Se você procurar a fonte para drupal_flush_all_caches()e clear_cache_all(), verá que nenhum gancho é chamado após a limpeza, o que é uma chatice de bug.

É muito difícil garantir que um usuário nunca precise esperar que algumas entradas de cache sejam criadas, por isso tento evitar o máximo possível de limpezas completas de cache.

Um método que realmente ajuda é alterar a página de desempenho para conectar um manipulador de envio que apenas limpa os caches voltados para a frente e não toca nos menus, no registro e nos caches principais semelhantes. Eu tive bons resultados com isso, pois a reconstrução de menus e registros leva cerca de metade do tempo para uma reconstrução completa do cache.

A outra coisa que eu tenho um script drush que faz um drupal_http_request()em todos os meus URLs (não apenas os importantes) para que tudo fique em cache. Como isso é feito varia de acordo com o site. Às vezes, posso apenas EFQ os nós publicados e criar URLs dessa maneira. Outras vezes, você pode consultar as tabelas do sitemap XML para obter seu URL. Eu chamo isso do meu sistema cron quantas vezes eu precisar.

mpdonadio
fonte
1

Duas opções:
https://www.drupal.org/project/cache_graceful pode ser exatamente o que você deseja.

https://www.drupal.org/project/apdqc possui 2 ganchos que disparam em uma limpeza de cache, permitindo alterar a limpeza drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);e depois permitir que você reaja à limpeza module_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);. Faça com que o APDQC funcione corretamente e defina $conf['apdqc_call_hook_on_clear'] = TRUE;no arquivo settings.php e os ganchos devem ser chamados sempre que uma limpeza de cache for feita.

mikeytown2
fonte
1

Isso pode não ser adequado para todos e pode não ser rápido o suficiente para o OP - pois é acionado apenas na inicialização da próxima página. No entanto, isso me ajudou a acionar o código logo após um "cache limpar tudo" que não era sensível ao tempo.

Obviamente HOOKprecisa ser substituído pelo seu próprio nome de 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.
}

Se você tiver um compartimento específico que precisa segmentar, o acima pode ser modificado para suportar isso, desde que o compartimento inteiro seja esvaziado no ponto em que o cache está limpo.

hook_inité executado apenas para páginas não armazenadas em cache. Embora como uma limpeza completa do cache não deva significar páginas em cache, isso não deve causar problemas. No entanto, sistemas de armazenamento em cache externos como o Varnish atrapalharão esse acionamento e significarão que só ocorrerá quando a próxima solicitação adequada retornar ao Drupal.

Também deve ser observado que, dependendo do seu sistema de cache - exatamente quando um cache_setse torna disponível para todos os usuários simultâneos -, esse gancho pode ser acionado várias vezes simultaneamente, especialmente se você tiver um grande número de usuários.

Pebbl
fonte
0

Eu tinha uma necessidade semelhante, em que um cliente queria liberar os caches Drupal e Varnish ao pressionar o botão "liberar todos os caches". Eu roubei esse item de menu para fazer isso.

Isso não atingirá nenhuma limpeza de cache no cron ou em qualquer outro lugar - apenas no link do 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
}
Travis Lilleberg
fonte
Thx Travis, mas estou procurando uma maneira que se encaixe em qualquer cache claro, não apenas o acionado voluntariamente por um usuário.
Gregory Kapustin
0

Você pode tentar https://www.drupal.org/project/recacher - ele usa o módulo Expiração de cache para detectar páginas expiradas e, em seguida, re-armazenar em cache somente essas páginas usando o excelente HTTPRL.

Vacilando
fonte