dylan's blog

A tiny cart block for Ubercart

dylan

Here's a tiny shopping cart block for Ubercart that fits right in with the menu. Of course the standard block could be themed this way, but this is handy when the design calls for the full-sized block elsewhere in the layout.

Quick Drupal Cacherouter and Boost benchmarks

dylan

In the discussion following my last post about cron and the cache hit rate, I promised to do some testing of the different cacherouter backends, as well as Boost. Again, these tests focus on the needs of a smallish site with 500 nodes and 1200 requests per day. Boost is the clear winner for response time (which shouldn't be a surprise given that it allows the web server to deliver HTML files directly from disk). What's interesting though is that the response times are all close enough that it doesn't really matter what caching backend you choose (An end user cannot perceive the difference between 6ms and 2ms, and throughput isn't an issue at this scale). The only factor that's really relevant is how good your system's cache expiration and regeneration logic is. I haven't yet had a chance to explore this aspect in detail, but it seems like Boost is the clear winner here as well.

cached response times

More complete breadcrumbs for Ubercart checkout

dylan

By default, Ubercart sets the breadcrumb on the checkout page to simply "Home", which I personally find a bit odd. Because it calls drupal_set_breadcrumb() late in the request cycle, it's not even possible to create menu links for use by the menu_breadcrumb or menutrails modules. Stranger still, the cart settings page offers a "Custom cart breadcrumb" text and URL option, but it's hard-coded to use a single link instead of a trail of links.

Here is a small snippet that will set the breadcrumbs to mimic the URL paths, for example:

Home › Cart › Checkout

How Drupal's cron is killing you in your sleep + a simple cache warmer

dylan

A lot of what's written about performance tuning for Drupal is focused on large sites, and benchmarking is often done by requesting the same page over and over in an attempt to maximize the number of requests per second (à la ab). Unfortunately, this differs from the real world in two key ways:

  1. Most of our projects aren't regularly driving traffic at millions of hits per day.
  2. Our users request a lot of different pages.

In this post I'll model a site with 500 nodes, and 1200 hits per day. That's fewer than 1 request per minute, yet for many small businesses this would be a fairly healthy traffic flow. In this case, it might at first seem that high performance doesn't matter. A clever hacker could probably manage to install Linux on the office coffee maker and get acceptable HTTP throughput. However, latency still matters a great deal, even for small sites:

User impatience is measured in units of 1 tenth of a second starting at 200 milliseconds or so.

Drupal's page cache is capable of delivering blazing fast response times, but only when the cache is warm. And the reality for most small to mid-sized sites is the page cache is being cleared out far quicker than it's regenerated.

hit rate
histogram

Repositioning node comments

dylan

A strange quirk in Drupal 6 hard-codes comment rendering into the node module. This makes it quite difficult to reposition comments, for instance under a set of tabs in the node template. Attempting this brings you crashing into the most dreaded rampart of Drupal theming; moving something out of it's vertical stack:
comments displayed as tab
comment_render($node) can easily be placed in your node template, but how on earth can the original display be removed? comment_render() is called by node_show(), which contains this nugget:

if (function_exists('comment_render') && $node->comment) {
  $output .= comment_render($node, $cid);
}

Ouch. (Thankfully, this has been fixed in Drupal 7.)

While it's tempting to fake it with jQuery, or CSS positioning, there is a way to fix this by overriding the page callback for node rendering. Here's a quick module that implements this solution:

Deployment with Capistrano Part 2: Drush integration, Multistage, and Multisite

dylan

In my last post, a basic intro to to running cap deploy was presented. Now, let's look at some more advanced scenarios. (See Part 1 for the actual task definitions described here).

  • Multistage: Deploy to different environments (such as testing vs. production).
  • Drush Integration: Use the power of Drush to extend Cap's reach into Drupal's internals.
  • Multisite: Run many sites from a single code base.

Capistrano: Drupal deployments made easy, Part 1

dylan

I'm a big fan of having an automated deployment process. It's really the web development analog to the "one step build process", as described in the Joel Test. In the past I have used various shell scripts to perform this task, but I have recently become a convert to Capistrano (or "cap" for short). With Capistrano, uploading your code to the test server is as simple as typing cap deploy. When you're ready to launch in production, it's just cap production deploy.

From capify.org:

Simply put, Capistrano is a tool for automating tasks on one or more remote servers. It executes commands in parallel on all targeted machines, and provides a mechanism for rolling back changes across multiple machines.

In detail, here are the features that got me hooked. There's a lot more that cap can do, and I'll describe some more tricks in part 2 of this post.

  • Atomic deployments with error checking. Cap uses a set of symlinked directories, and the links are updated during the final step. It also won't allow a deployment to keep plowing ahead if an intermediate step fails. This makes your deployment atomic; it will either fail or succeed entirely.
  • Fast rollback. If something does go wrong, getting back to the previous state is as simple as cap deploy:rollback.
  • Parallel execution. If you use multiple servers in a load-balanced environment, cap can make managing them easier.
  • Multistage deployments. "Stages" are different server instances of your code. You may have different servers for development, content entry, and production. With the Multistage extension, cap can share code for common tasks between these stages.

SimpleTest 6.x gets e-mail capture!

dylan

One email was captured.
The latest 6.x-2.9 release of SimpleTest includes a backport of the e-mail capture feature from D7. This means you can finally unit test e-mail sending functionality! There is still one bug to be ironed out, but a patch is available.

iPhone video streaming from Drupal's file system

dylan

It's well known the iPhone can play H.264 video. With tools like ffmpeg, hooking this up to Drupal ought to be simple, right? Here are a few snags I hit, and how to resolve them.

Bulk generating menu hierarchies

dylan

If you have ever needed to bulk generate menu items in Drupal (I used this for theming some drop-downs), here is a snippet to accomplish it. The third parameter is for recursively creating a hierarchy, so be careful with it – you can blow up the menu admin page in a hurry!

This code requires the devel module; the ambitious reader might consider adapting this to patch devel itself.

Syndicate content