1

I'm working on a Drupal 7 site where nodes represent jobs in a queue. When a node is created, a custom module with hook_node_insert launches another program using exec. This program tells Drupal that the job has finished by requesting a page on the site at site.com/jobcomplete/NODE_ID/IS_ERROR. The callback for this page then does:

$node = node_load((int)$node_id);
$node->field_completed[LANGUAGE_NONE][0]['value'] = ($error == 1) ? -1 : time();
node_save($node);

The problem with this is that sometimes the program errors out almost as soon as it's started. When this happens the callback is called before the request that created the node in the first place is completely finished, resulting in 'PDOException: SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded' when node_save is called.

How can I get the callback to wait for the request that created the node to finish before trying to update it? sleep() doesn't seem to work.

Thanks.

2
  • you're running into a race condition essentially, the web is stateless. You need to setup some sort of job and worker queue. Maybe with a bit of code you can use the Progress module, drupal.org/project/progress
    – tenken
    Commented Jan 4, 2013 at 21:41
  • @tenken: Picking Drupal for the website wasn't my call. If I were to start this project again, I'd go with Django because the programs called are in Python and queuing is handled by Celery.
    – njbooher
    Commented Jan 4, 2013 at 21:51

1 Answer 1

2

Drupal provides a Lock API for this purpose - to handle when multiple processes are competing for a resource.

In your case, you need to acquire a lock and release it when finished, checking if that lock is available prior to processing from the other component.

i.e:

Although not directly related, you may also be interested in the Queue API for other queue based processing tasks.

2
  • +1 actually this looks like a solution for his problem easily. Simply acquire a lock before he exec's and then release it in his callback then node_save.
    – tenken
    Commented Jan 4, 2013 at 22:52
  • 1
    While looking into where I would put the lock I realized that hook_node_insert is called before the node is actually saved to the database, and that what I really needed was a hook after the database save, which doesn't exist. A workaround is described here.
    – njbooher
    Commented Jan 4, 2013 at 22:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.