I wanted to add an additional storage type to my boost cache. My module, Tournament Brackets, can generate an image of a tournament bracket as part of the default node view. If the bracket node is at say node/1234, then an image is generated at node/1234/bracket-image inside the node. Of course, the node html was cached perfectly by boost, but the image part was not. So, implemented hook_boost_storage_types() to add a PNG type:

function bracket_boost_storage_types() {

  $types = array();
  
  $types['image/png'] = array(
    'title'           => t('PNG'),
    'description'     => t('PNG output'),
    'extension'       => 'png',
    'enabled'         => FALSE,
    'gzip'            => FALSE,
    'lifetime_max'    => 3600,
    'lifetime_min'    => 0,
    'comment_start'  => '<!-- ',
    'comment_end'    => ' -->',
    'variants'        => array(),
  );

  return $types;  
}

And added the required .htaccess code (generated by boost) and the images were cached as well. So far, so good. The module improves the performance of the site tremendously.

I'm also using the expire module to automatically delete cached nodes when they are updated - and therein lies my problem. The node html was expired correctly on node updates, but the image part was not.

I browsed around in expire and found hook_expire_cache_alter() which allows the expired url list to be updated when a node is expired. Here's my implementation:

function bracket_expire_cache_alter(&$urls, $object_type, $object, $absolute_urls_passed) {

  if ($object_type != 'node' || !isset($object->type)) {
    return;
  }
  if ($object->type == 'bracket') {
    $urls['node-' . $object->nid . '-bracket-image'] = 'node/' . $object->nid . '/bracket-image';
  }
}

However, when the node is expired, boost wants to delete the file: .../node/1234/bracket-image_.html - which is incorrect - it should be .png. It looks like boost_expire_cache() uses the header info of the current page (html) to form the file extension.

In order for this to work, I ended up passing the file extension in bracket_expire_cache_alter():

  if ($object->type == 'bracket') {
    $urls['node-' . $object->nid . '-bracket-image'] = 'node/' . $object->nid . '/bracket-image_.png';
  }

as well as patching the boost_expire_cache() code to allow a url with an extension to be passed in and if so not appending the .html extension.

I was wondering if the module developers had a better solution - I feel like mine is sort of a kludge...

Thanks!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jimbullington’s picture

Title: Implementing hook_boost_storage_types » Implementing hook_boost_storage_types()
Anonymous’s picture

Hi,

Let me just understand this, node/1234/bracket-image would be a call to your module that dynamically outputs an image every time by default, without boost installed ?

It's not quite clear as you mention the previous URI and then boost looking for .../node/1234/bracket-image_.html instead of .../node/1234/bracket-image_.png and your module page details pdf output (I know the fpdf project very well).

There's a distinct possibility that you are appending corrupted data to the ends of your images with the comment start and end, as normally that's a boost timestamp in a text document.

jimbullington’s picture

Thank you for your comments.

Let me just understand this, node/1234/bracket-image would be a call to your module that dynamically outputs an image every time by default, without boost installed ?

Yes, in image mode, the node view is rendered like:

<div class="bracket">
 
 <div class="bracket-print-link">
  <a href="/node/7872/bracket-pdf">Click here for a printable version</a>
 </div>
 
 <div class="bracket-img">
  <img src="/node/7872/bracket-image" />
 </div>
 
</div>

The image is cached for anonymous users by the default Drupal cache - if enabled. The performance with Boost is much better since it is a file cache.

It's not quite clear as you mention the previous URI and then boost looking for .../node/1234/bracket-image_.html instead of .../node/1234/bracket-image_.png and your module page details pdf output (I know the fpdf project very well).

The module will output PDFs as well, but I'm not caching those - they are much less frequent.

There's a distinct possibility that you are appending corrupted data to the ends of your images with the comment start and end, as normally that's a boost timestamp in a text document.

Indeed, you were correct. I have set comment_start and comment_end to FALSE.

I've uploaded the patch to boost.module that enables a url containing an extension to be passed to boost_expire_cache() - I'm not sure that was the right direction, but it seems to work for me.

Thanks!

Anonymous’s picture

Hi, I had a think about this while waiting for the reply and I do think that it would almost certainly be better if your module whereto have it's own cache. Drupal core has it's own cache for images, css aggregation etc... and I think that if for example someone wanted to use your module with varnish or memcache or authcache then it would slot right in, rather than insisting on using boost.

jimbullington’s picture

OK - despite the extra coding, boost seemed to be the easiest to implement on short notice.

I had an image cache in the module, but it was slower that just letting Drupal cache the images. A file cache, avoiding the Drupal database, seems to perform the best.

Thanks for your help and suggestions - I'll look into the other options.

Anonymous’s picture

I think using similar .htaccess rules to boost would be a good idea, then you could fine tune it or whether someone is logged in or not, or https is used, and then it would be a simple matter of

if(file_exists()){

}

I know what a memory hog fpdf can be, if you look at http://www.fpdf.org the scripts section, there is a memory optimisation script I wrote 12 years ago that worked very well, it uses disk caching and ensures that the memory can never be overloaded. Then I believe your module would just need a simple hook into cron to clean up if required that the image was updated or limiting it to authorised users only would regenerate the content and at least enable other caching methods, whereas boost together with something like varnish has created issues that require disabling vanish entirely every time an edit is required, in general I'm thinking that by containing your own cache would give your audience more options which seems sensible.