The Only Reason My App Worked Was Due to a Slow Database
Things Are Not What They Seem
Astonishingly, the only reason my Ajax driven web app has been able to run consistently and successfully for the past two years is due to MySQL latency.
I know this because yesterday (with the help of Jonathon Hill) I optimized the database by moving it off the server and onto it’s own 4GB Rackspace instance. (Everything was running on a single 2GB Rackspace instance prior to this).
As soon as I got the new database up and running it was blazingly fast (using the Percona flavor of MySQL made it a breeze).
But today I noticed that the load average on the front end head server (now MySQLless) was running super high (100+) with customers being unable to login and generally use the service.
After some digging around I noticed that Ajax requests were being served wayyy faster allowing for each client to establish 5-10 concurrent ajax requests thus flooding the Apache child pool – amping up the load – and bringing down the site.
Semi-blocking Ajax Queue
To fix this I quickly implemented a semi-blocking queuing system for all Ajax requests.
Basically the JavaScript now queues all ajax requests the client sends and only makes one ajax call at a time UNLESS a call is blocked for more than one second, then it is allowed through.
This allows the javaScript to be asynchronous but severely throttles asynchronousness (if that is a word!) concurrency.
I was expecting this to slow things down but it seems to have really speeded things up from both a user and backend perspective.
But perhaps even more importantly the server load average has gone from 100+ down to 0.2.
I can only assume the reason the system has been working for the past two years is because MySQL latency was forcing the Apache child processes to run slower, with a knock on effect of Ajax responses being slower, with a knock on effect of chained Ajax requests being delayed thus creating a less asynchronous environment.
In other words, the only reason my app worked for the past two years was due to a slow database!
How I Converted My Subscription Site from Paypal to Stripe in 2 Days
PayPal to Stripe in 2 Days
Stripe.com is a dream for any developer wanting to build payment processing into their site.
In fact, the API is so easy to use it leaves me wondering why many other API’s make such a mountain out of a molehill. Stripe goes one step further by making every part of website payment integration stupidly easy.
App Store Approval = Days –> Stripe Approval = Instant
For example, have you ever tried to get approval to join the App Store and start making money? It takes hours of form filling and fact checking, then days of waiting. With stripe you only need to fill out a single form with your company information and tax ID. Then click a button and – bada-boom bada-bing – you can start collecting money online instantly.
(Assuming you live in the USA and have your company papers in order.)
PayPal Sandbox = Hours –> Stripe Sandbox = Instant
Another example is with PayPal, if you want to use the sandbox to test your application it takes hours of fiddling around setting up a sandbox account loging in and out of various vendor, seller accounts etc. But with stripe it is as simple as clicking a swich that says “test” and using a pre-assigned test API key.
Even better than that, all the documentation auto inserts a working test API key into any example code so you can literally copy/paste from their site into yours and things work.
Merchant Account = Headache –> Stripe = Merchant Account
You probably already know this, but just in case you didn’t, stripe does not require a merchant account. Simply enter your existing bank routing and account number and stripe sweeps money into your account on a daily basis (with a 7 day lag per sweep). Setting up a merchant account usually takes weeks and requires hours of paperwork to be filled. Most other payment gateways require merchant accounts.
Subscriptions
The subscription side of things is also super easy. Just add a few subscription plans in the stripe control panel and sync the plan ID’s with the ones you are already using on your site. When a customer switches plans stripe does all the annoying prorata stuff for you out of the box (so your customer doesn’t loose money and you don’t have to fiddle around with PayPal partial refunds).
They also have a nice and simple way of getting invoices out the API into your system so you can show customers exactly when what they paid for.
How I Switched in Only 2 Days
The trick here was to keep my infrastructure exactly the same. The only change I made was to the PayPal endpoint (i.e. the PayPal IPN script). At the top of the IPN script I check to see if the request is from PayPal or Stripe. If it’s from stripe I convert Stripe JSON parameters to PayPal IPN POST parameters. Hey presto everything works in an instant.
To get going the only new stuff I needed to add was a credit card form and a cancel button and test, test, test for a day or so.
Nuking Test Data
I was just about to write to the stripe team to suggest it would be awesome if they had a way to nuke all my sandbox test data… but then I wondered if they already had it. In the settings control panel I found a button marked “Clear Test Data”. Simple as that.
Conclusion
Due to the above PayPal IPN trick, ease of testing, ability to erase test data and instant go-live approval I converted my subscription site from PayPal to stripe in only 2 days. I switched it live on day 3. Not too shabby.
I don’t usually rave about this kind of service but they built something in a way that I would have loved to build myself. These guys really thought this through from business to UI to documentation to technology.
Awesome job guys!
1 to 1000 in PHP With No Conditionals or Loops
Inspired by this post (a puzzle challenge asking if you could think of a way to print from 1-1000 in C++ with no conditionals or loops)
I wondered if I could think of a hack to do it in PHP… here’s my hack!
<?php
sleep(1);
$i = ++$_GET['i'];
$go[1000] = 'http://google.com?';
header("Location: {$go[$i]}/?i=$i");
?>
It’s a PHP script (index.php) running from the root of a server with warnings switched off.
As an added bonus you need to watch http live headers to see the “print” out 😉
(Note: It’ won’t work in most modern browsers as they tend to have a limit of 20 redirects. Meh. That’s just a technicality.)
How to get the mime type of a remote file in php (with redirects)
Just in case it’s of any use to anyone else out there, here’s a function that can get the mime type of a remote file. It will also follow any redirects that are in place.
function get_url_mime_type($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_exec($ch);
return curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
}