Tuesday, September 28, 2010

Authcache - detailed documentation

Authcache is drupal community contributed module you can find here Authcache project page. The Authcache module offers page caching for both anonymous users and logged-in authenticated users. This allows Drupal/PHP to only spend 1-2 milliseconds serving pages, greatly reducing server resources. Please note that enabling authenticated user caching will require modifying how your user-customized content displays on your pages. You should be an experienced Drupal developer if you choose to implement the full functionality of this module. Anonymous caching won't require any changes and will offer a speed improvement over Drupal core since hitting the database can be completely avoided.

Authcache Installation
To install authcache module you need
  1. Download authcache module and extract it to drupal contrib modules dir (usual /sites/all/modules).


  2. Override cache_inc variable by adding $conf['cache_inc']     = '{path to authcache module}/authcache.inc';  (usualy $conf['cache_inc'] = './sites/all/modules/authcache/authcache.inc';)
  3. Enable     Authcache module in drupal admin part url /admin/build/modules/list
  4. Config     Authcache in drupal admin part /admin/settings/performance/authcache     (Check what roles will use caching and etc.)

How Authcache works?

Authcache need to select authcache.inc as cache.inc file. Such mechanism is used by drupal system to change cache implementation. Memcache, Cacherouter and several other modules uses this mechanism to change cache implementation (use db, memcache or something else for cache). Authcache realy does not change cache implementation. It check what cache module (support drupal native cache, memcache and cache route modules) is enabled and include it's cache implememnation (authcache/authcache.inc:str 22). authcache.inc also handle authcache ajax requests (authcache/authcache.inc:str 70). Authcache Ajax requests differs form all other requests by custom HTTP header - HTTP_AUTHCACHE. The other goal of authcache.inc is page_cache_fastpath function (authcache/authcache.inc:str 81) that called by drupal core on bootstrap EARLY_PAGE_CACHE step (/include/bootstrap.inc:str 1135). On picture 1 you can see authcache workflow diagram. Realy step 2.2 bootstrap EARLY_PAGE_CACHE step runs before step bootstrap FULL step 1.2, but if page_cache_fastpath returns null that means we have not current page in cache and need to generate it. Then we run all next bootstrap steps – step 1.2. On bootstrap FULL (step 1.2) we runs hook_init. Authcache on hook_init determinates if current page should be cached (authcache/authcache.module:str 113).
Picture 1 – Authcache workflow
 

None Cached page request
For pages that should be cached authcache module set global flag $is_page_authcache = TRUE and
register_shutdown_function('_authcache_shutdown_save_page');
that will save rendered page to cache step 1.6.

WARNING: _authcache_shutdown_save_page function also checkes if $is_page_authcache == TRUE. If some code (function X()), that runs between hook_init and shutdown function, will set $is_page_authcache = FALSE will cause such behaviour:
  1. page would not save in cache
  2. functions implements authcache, that runs before function X()), will realize authcache behavior
  3. functions implements authcache, that runs after function X()), will realize simple behavior
Such things can be reason of bugs. Authcache module have function X() like code (authcache/authcache.module:str 420). It set $is_page_authcache = FALSE if there as durpal messages on page.

You can manage what pages should be cached and what not on this page /admin/settings/performance/authcache/pagecaching in drupal admin part. Cache key depends of roles current user have (authcache/authcache.helpers.inc:str 314). It means that users with equal roles list will use same authcache, and all user specific conent need to get dynamic. All other implementations of authcache is responsibility of plugins to it. You can find authcache api desciption in chapter Api implementation.

Cached page request
On bootstrap EARLY_PAGE_CACHE page_cache_fastpath (steps 2.2, 2.3) function get's html from cache and returns it. Remember that modules do not includes.

 

Authcache ajax request 

After cached page getted by browser js sends can send authcach ajax request using function Authcache.ajaxRequest(jsonData) (authcache/js/authcache.js:str 149) (step 2.5). This request differs of simple ajax request, because authcache adds custom HTTP header - HTTP_AUTHCACHE.

 

Server side callback 

JsonData should be array of struct array(key => data). Key should be name of module that handles authcache for current request. Key will be used to determinate php function that will be called as ajax callback on php side. That function should have name _authcache_{key}. data that will be passed as argument into that function.

 

Client side callback

The same way we have determinate callback on client (browser) side. Result of autcache ajax request should be array with such structure array(key => data). Key should be name of module that handles authcache for current request. Key will be used to determinate js function that should process data we getted with ajax. That function should have name _authcache_{key}.
Such way is low-level, differs from drupal style and not very usefull. Easy Authcache makes implementation easily.

 

Server side workflow

As described in chapter How Authcache works? authcache.inc determinates if current request is authcache ajax (authcache/authcache.inc:str 70). If we are dealing with authcache ajax, it includes authcache.php. That file run bootstrap SESSION step (step 2.6), includes custom functions that are placed in authcache_custom.php, and call server side callback functions (_authcache_{module name}) (authcache/ajax/authcache.php:str 47).

WARNING: Authcache uses GET method for authcache ajax request, because GET is faster then POST. But length of url is limited. This can be reason of bug. Be carrefull with this, especialy with if you are using suhosin patch. Smoke of this problem is that on some pages that have a lots of regions getted with ajax you have empty result of authcach ajax request.

 

Client side workflow

Authcache do not send ajax request by default, it jsut provide api to do this. You custom module that implements authcache api should
  1. Provide all params that required on ajax server side
  2. Send ajax request with function Authcache.ajaxRequest(jsonData) (step 2.5)
  3. Provide js function _authcache_{custom module name} that will process result of authcache ajax result. (step 2.9)

Authcache api implementation
If you need to implement authcache you have to write this code.
example_module.js
$(function() {
   var ajaxJson = {
       'max_age': 3600,
       'example_module' : 'value1',
   };
   if (typeof(Authcache) != 'undefined') {
       Authcache.ajaxRequest(ajaxJson); // (step 2.5)
   }
});

// Client side ajax call back // (step 2.9)
function _authcache_example_module (data) {
   context = $(data);
   $('#dynamic_ajax_block').replaceWith(context);
   Drupal.attachBehaviors(context);
}
example_module.module

   function example_module _block($op = 'list', $delta = 0, $edit = array()){
       switch($op){
           case 'list':
               $blocks = array();
               $blocks[0] = array( 'info' => t('Dynamic block'), );
               return $blocks;
           case 'view':
               global $is_page_authcache;
               switch($delta){
                   case 0:
                      if ($is_page_authcache) { // (step 1.4)
                          drupal_add_js(drupal_get_path('module', 'example_module') .'/example_module.js', 'module');
                          $content = '';
                      } else {
                          $content = 'Real content';
                      }
                      $block = array( 'content' => $content, );
                   break;
                }
                return $block;
             break;
          }
     } 



Add function _authcache_example_module to authcache/ajax/authcache_custom.php

// (step 2.7)
function _authcache_example_module($data) {
   if ($data == 'value1') {
       return 'Real content';
   }
}

This is very simple implementation. I think that more detailed description is unnecessary for developer familiar with Drupal. Feel free to contact me to for feedback.

2 comments:

  1. Awesome, thanks for writing this!

    ReplyDelete
  2. I'am relative a Drupal newbie. I have a site with 3 different roles auth users. I'ts a small site and not so busy but very usefull for members of our society. I'am looking for a separate build program to 'warm' the auth cache in the nightly hours. It seems to me that your article should be usefull. Do you have some suggestions to help me in the right direction?

    Regards,
    Jan Walhof

    ReplyDelete