Monday, November 22, 2010

Борис Гребенщиков

Reminder, good songs:
Psi (Пси) - Аквариум (CD)
Сварог

/////////////////

Bardo - Русско-Абиссинский Оркестр (CD)

/////////////////

Прибежище - БГ, Gabroelle Roth & The Mirrors (CD)

Example of using fastcgi_finish_request() in php 5.3

Warning: this technique will work only when php is run as fastcgi and controlled by php-fpm

http://php-fpm.org/


fastcgi_finish_request() is extremely powerful optimization trick. It's even more powerful if you use it together with closure functions in php 5.3
This is how I started using it now:
suppose I have a method somewhere in the middle of my script that has to call some API, let's say Facebook API, download recent user data and if something changed in user's Facebook profile, then update my database.

Since facebook API response time is unpredictable, I don't want to hold up the page load waiting, so I want to defer this call till after the page is rendered.

But how do I do this if the Facebook api check is somewhere in the middle of my script and the page has not finished rendering yet?

The way this can be done is with closure.

Pass anonymous function as callback to register_shutdown_function() like this:

This script snipped is somewhere inside a class method which is called about half way through the script:
Note: the d() and e() functions are for logging debug and error messages,
you can ignore these...


$oAuthFB = new clsExternalAuthFb($oGlobal, $sAppId, $aCookieParams);
register_shutdown_function(function() use ($oAuthFB){

try{
d('before facebook auth post precessing $oAuthFB: '.$oAuthFB);
$oAuthFB->getFbData()->getFacebookUserObject();
d('after facebook auth post precessing');
} catch (Exception $e){
e('Unable to run post processing of FB data: '.$e->getFile().' '.$e->getLine().' '.$e->getMessage());
}
});


See what's going on here? I am basically cutting out the piece of code and sticking it to be executing all the way at the end of the script, after the php is done parsing everything else.

The only thing left to do is to add

fastcgi_finish_request();
somewhere after the output is sent to browser.

For example, in my index.php I have

$oController = new Controller();
echo $oController->getHtml();
fastcgi_finish_request();


That would ensure that all registered shutdown functions are run after the output is sent.

Because of the closure, the context, the object $oAuthFB is remembered it the state it was just before the callback anonymous function was created, all instance variables are in place, so the shutdown function is executed with the complete context of $oAuthFB object in the same state it was back in the middle of that method where I registered the shutdown callback.

This is extremely powerful way to basically cut out the code from the middle of you script and defer its execution till after the page has been rendered.

Tuesday, November 16, 2010

To update classes to make use of php 5.3 static magic

Something for my own user only, some changes to make to program
Even better have clsEmailRecord::factory($oRegistry)->get($email)
Then we can also create new record this way! it should extend clsMongoDocument

Just extend static class MongoDocument then use get_calling_class()
and call_static() magic
then it will be as easy as just
creating blank classes than extend clsMongoDocument
Heck, we can even make it serializable, just
use clsRegistry::getInstance() in unserialize and we good to go

clsMongoDocument::getByEmail($email)
clsMongoEmail::getByEmail($oMongo, $email)

clsMongoEmail::create($oMongo, $aData);

clsMongoEmail::factory($oMongo, $aData); the normal object