by Alexander Novikov
I work at PubNub on the client SDK team with Geremy Cohen,
Director of Client Engineering.
I am one of the maintainers for the PubNub library for PHP, and was tasked by Geremy to write a blog post about my work.
PubNub has a lot of client implementations today, even languages as new and exotic as Dart. PHP, being the close 3rd (after C and Java) most popular programming language worldwide also needs one.
To be usable, every library has to support almost any version of its language translator/SDK possible. This is usually not a big deal, it's uncommon for a Java application to crash or fail to compile when the next JDK is released. Not so with PHP. First idea was to have several versions of the code for every major release of PHP, but as changes and fixed will start flowing, it will quickly descend into unmaintainable mess. Having a single version of codebase seemed impossible, mainly because namespaces are missing from versions prior to 5.3, and those are still in common use today.
After some doubt, i decided to make a single codebase which is written in pseudo-code, not directly compatible with any PHP version, calling it 'php', and a simple preprocessor to build out code applicable for a given version out of it. If you want to change something in the functionality, you should just change *.php files in ./core/src folder of the project, and then run ./build.sh in ./core. Voila - your files are up-to-date for latest versions and old ones like 5.2! Ability to do so helps a lot to automate building and testing.
Next question was unit tests – which is especially multiplied by the diversity of PHP behavior dependent on the version of interpreter. I've covered most functions with phpunit tests, but then i faced another problem. PubNub developers normally use Jenkins for most of their projects to manage and automate testing process, but we've faced an issue with switching of PHP version. Jenkins was not designed for PHP testing, and it doesn't have native possibilities to pick different versions for tests. There exists a wonderful tool, PHPBrew, that helps with such switching... and has one more issue: after small investigation i found known problems with php 5.2. So it's the reason why it was needed to choose another autotesting tool.
Picking between several options, i eventually chose Travis-ci. Travis is a good choice for automate testing in direct meaning. You don't need to think about storing source code on some servers (or local machine, or...), you configure testing system once and it loads all current code fixes automatically from github and does a coverage. As i expected, it turned out that most of the existing PHP releases, except a couple i tried it on myself before, failed some tests. It could take a lot of work to find it out otherwise, because setting up every PHP version manually will also pull with itself a lot of incompatibilities with other libraries – imaginable if i set up many virtual machines for tests, but i am happy i avoided it.
Many applications need asynchronous calls. Some PubNub features like heartbeat are inherently asynchronous. How to implement it in PHP application? PHP is meant to run synchronously. There is some multithreading support with libraries like pthreads, but that isn't very stable and not widely used. I tried to build async features into PubNub client code, and even had several working functions, but at last i given it up: it really makes the code non-friendly from the point of view of PHP paradigm. The most appropriate functions for PHP usage are publish(), presence and security functions, async calls should be left to different technologies.
For better performance, HTTP pipelining was implemented. This method gives opportunity to send several server requests simultaneously and as a result application shows better average response time.
Working on PHP client library rewrite for PubNub, i faced many interesting tasks, all done to optimize throughput, unify codebase and provide full test coverage. It is now ready for production use and apart from asynchronous calls, provides interface to everything PubNub has to offer. Enjoy!