I just started working with Advanced Queues with the Commerce Billing module.

My D7 test site currently runs cron tasks via crontab:

*/15 * * * * /usr/bin/drush --root=/var/www/html --quiet cron

But it seems that the Advanced Queues aren't run with that task. I had to add this additional task to my crontab to get the queues to process:

*/15 * * * * /usr/bin/drush --root=/var/www/html advancedqueue --all --timeout=60

It looks like there's a way to run Advanced Queues via "poor-man's" processing via cron in the docs, but I'm not quite sure how to accomplish that.

Of course, I also don't know what 'best practice' is for running Advanced Queues in general. Are two lines in crontab a better way to go?

Thanks for any support!

Comments

cmarcera created an issue. See original summary.

cmarcera’s picture

Issue summary: View changes
cmarcera’s picture

For now I've settled with the following cron schedule:

*/5     *       *       *       *       /usr/bin/drush --root=/var/www/html cron --quiet
*/5     *       *       *       *       /usr/bin/drush --root=/var/www/html advancedqueue --all --timeout=259

Still not sure if that is reasonable or what best practice is. I'd still love any feedback!

nvahalik’s picture

There are two methods that I've personally used to run AQs. The first is the crontab and the second is a process manager.

Using crontab

Crontab can be an effective way to handle your queue jobs. As you already pointed out the use of the --timeout param lets you specify how long you want that queue worker to live and it's generally a good idea to keep it right around the time of the jobs. Note that running multiple queue workers can be OK, too. If you want to run more, you can "ramp up" by doing a job that runs every minute and having runners that run for 3 minutes, or jobs that run every 5 minutes but last for 15.

There are several things to take into consideration here:

  1. Startup and job time - Note that every time you start up AQ, Drupal has to be bootstrapped and so when you run a worker for 1 minute, you'll be spending anywhere between 2-10% of your time just bootstrapping Drupal. Depending on your workload, this might or might not be acceptable (if you have jobs that take 30-seconds to complete, this might cause you to only get one done per worker.
  2. How stable/error prone is the code? - Cron will not automatically restart a failed process so if you have errors in your workers, the amount of time between startups means that you'll potentially lose processing time. Thoroughly testing and ensuring proper error handling is key (no matter what)—but it is more of an issue in this method.

Using a process manager

The other way to do this would be to use some sort of a process manager. A process manager will keep the process alive until it is either killed or if the process itself signals that it wants to exit gracefully. In a recent project, I've used a combination of the screen command along with a bash function called forever to run AQ workers until they either signal for exit.

There are some caveats with this approach too:

  1. Long running processes not pick up code or config changes - In some cases your code might run for hours (days?) before it either runs out of memory or hits some sort of error. Code pushes and config changes (variables, cached data) won't update automatically and so unless you're sure you're not going to be needing those things, you'll have to make sure that you are restarting these processes every so often
  2. Be wary of thrashing - Process managers will continue to restart processes until they are killed off, so it's possible to have these processes trying to bootstrap Drupal continuously until that problem is fixed.

Here's a copy of the forever "process manager", which is really just a bash script that restarts processes unless the process sends a signal saying that it is done.

function forever () {
  COMMAND=$@
  EXIT_STATUS="255"
  while true; do
    $COMMAND;
    EXIT_STATUS=$?
    if [ "$EXIT_STATUS" -eq "131" ]; then
      echo "Command $COMMAND exited successfully."
      break;
    elif [ "$EXIT_STATUS" -eq "130" ]; then
      echo "Command $COMMAND restarting gracefully."
      sleep 1
    else
      echo "Command '$@' crashed with exit code $EXIT_STATUS.  Respawning..." >&2
      sleep 1
    fi
  done
}

function pquit() {
  echo "Sending SIGQUIT to $1..."
  kill -s SIGQUIT `pgrep -f $1`
}

function pint() {
  echo "Sending SIGINT to $1..."
  kill -s SIGINT `pgrep -f $1`
}

function pstop() {
  echo "Sending SIGSTOP to $1..."
  kill -s SIGSTOP `pgrep -f $1`
}

function pstart() {
  echo "Sending SIGCONT to $1..."
  kill -s SIGCONT `pgrep -f $1`
}

Note that these commands are to be used in tandem with the patch in this issue: #2916304: Support signal handling in drush process queue command.

nvahalik’s picture

Component: Code » Documentation
Status: Active » Closed (works as designed)

BTW I'm marking this as closed—but if docs need to be updated we can certainly do so.