Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm writing some plugins that do background batch processing, i.e. operations that take longer than 30 seconds. I'm creating objects with the necessary job parameters set like this (this is a hugely simplified example):

class MyPlugin_Create_Terms {
    public $job_id;
    public $terms;
    public $taxonomy;
    public $created = 0;
    public function init( $terms, $taxonommy ) {
         $this->job_id = uniqid();
         $this->terms = $terms;
         $this->taxonomy = $taxonomy;
         return $this->job_id;
    }
    public function do_job( $object_storage ) {
         foreach( $this->terms as $term ) {
             wp_insert_term( $term, $this->taxonomy );
             $this->created++;
             $object_storage->save_object( $this->job_id, $this );
         }
    }
}

$create_terms = new MyPlugin_Create_Terms();
$job_id = $create_terms->init( $_POST['user_input_terms'], $_POST['user_input_taxonomy'] );
$object_storage = new MyPlugin_Object_Storage();
$object_storage->save_object( $job_id, $create_terms );

And in another process:

$object_storage = new MyPlugin_Object_Storage();
$create_terms = $object_storage->load_object( $job_id );
$create_terms->do_job( $object_storage );

While anywhere else:

$object_storage = new MyPlugin_Object_Storage();
$create_terms = $object_storage->load_object( $job_id );
echo "We have created {$create_terms->created} terms.";

Now the problem is implementing the Object_Storage. I have figured out the following options for storing objects:

  1. Transients. They apparently won't do, since they have no guaranteed life-time (with caching, the transients might never be written to the database, I've learned).

  2. Existing DB tables. Serialized PHP objects should not be saved to MySQL text fields, since they might contain NULL bytes (( I had a spectacular WSOD failure when serializing an object with a protected property to the usermeta table) :

    Note that this is a binary string which may include null bytes, and needs to be stored and handled as such. For example, serialize() output should generally be stored in a BLOB field in a database, rather than a CHAR or TEXT field. - PHP Manual: serialize()

  3. Creating a custom table with BLOB type fields for serializing any object or alternatively, storing the object data without serializing. Feels like overkill. What are the best practices?

  4. Using the filesystem. Various factors like locking, atomic and non-atomic processes and file permissions complicate this. Specifically, since there will be two processes accessing the object concurrently, there is the problem with race conditions when they need to look at the same object.

  5. Using _SESSION? Probably not good for two concurrent processes.

Any thoughts would be appreciated!

share|improve this question
    
Multi-process tasks are not common to WordPress (sans wp-cron, which is not quite elaborate solution). My opinion would be to look for prior art in general PHP development, before deciding on implementation details in WP environment. –  Rarst Feb 12 at 18:39
1  
One the one hand, there're Iterators in PHP SPL that implement Serializable - you can do the same for custom classes. When I read through your "problem", then I ask myself what you're really (in detail) trying to do. Currently it's just "background process" and some buzzwords that aren't really related: protected properties & serializing object, filesystem components, Session, extra tables. Please file an edit and show us (in code as well) what you're really trying to do. Leaving it open... –  kaiser Feb 14 at 10:29
    
@kaiser: Edited. –  P_Enrique Feb 14 at 18:54

2 Answers 2

up vote 1 down vote accepted

Store the object temporarily in the database, but implement __sleep() and __wakeup() to avoid side effects.

Alternatively, implement the Serializable interface and prepare the data in its methods. There is no need to store NULL values.

share|improve this answer
    
I think this is the way to go. I had implemented a __sleep() function, but it let slip a protected property, which gets serialized as with the key \NULL*\NULLpropertyname. Private properties get serialized with the key \NULLclassname\NULLpropertyname. So you have to take care to serialize only public properties. –  P_Enrique Feb 12 at 20:21

Long term, you should consider that if you have a process which is going to regularly exceed the max execution time, then running it from inside an HTTP request and polling isn't a great idea. Consider using the real cron system instead. Command line PHP processes don't have a max execution time, normally, and can run until completion.

Short term, if you want to store it safely in a text field, like in a custom post type or meta or something, serialize it, then base64_encode the string. This will solve your problem with the null bytes. Just decode it and unserialize it when you need to retrieve it again.

share|improve this answer
    
This is about processes launched by the user, not scheduled maintenance jobs. I know of three ways to run a process on the background avoiding a browser timeout, out of which the command line process seems to be the most prone to break: users might now have exec rights, the php interpreter might be in an unknown location, and you'll have to fake _SERVER vars to get WordPress to load. The base64_encoding is an interesting idea. –  P_Enrique Feb 12 at 20:58
    
Also I want to mention that on my laptop, deleting 40 attachments is enough to cause a timeout. I'm trying to design something that will work on blogs that might have thousands of posts, so timeouts are a big issue. –  P_Enrique Feb 12 at 21:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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