Asynchronous PHP

Florian Engelhardt

The Problem

The customers are waiting too long at the checkout

Stuff that happens during checkout

  • persist the order and modify stock
  • send tracking data to services
  • send order confirmation email
  • capture money from payment gateway

Summary

The customers are waiting for things they …

  • … don’t know about
  • … don’t care about

Disclaimer: If you have something that works for you, stick with it!

How RabbitMQ works

This is highly simplified 😉

Asynchronous Consumer

  • consume the messages from RabbitMQ
  • send tracking data to service via HTTP
  • non blocking / async
  • written in PHP

Why PHP?

Why don’t you just use Node.js?
— RandomUserAtStackoverflow

But really, why PHP?

  • has the native functionality to write async code
  • there are cool libraries doing the heavy lifting for you
  • these libs work on core php w/o extensions
  • you already understand it anyway

Disclaimer: It is still a good Idea to checkout a new language every now and then!

Let’s build something!

aka Demo time!

A fully working example on two slides!

Disclaimer: Please don’t!

The connection

$client = new \Bunny\Async\Client();
$browser = new \React\Http\Browser();

$app = ....

$client->connect()->then(function ($client) {
    return $client->channel();
})->then(function ($channel) use ($app) {
    // waiting for messages
    $channel->consume(
        $app,
        'hello'
    );
});

React\EventLoop\Loop::get()->run()

The App

$app = function ($message, $channel, $client) use ($browser) {
    $body = json_decode($message->content);
    $promises = [];
    foreach ($body->orderedItem as $orderedItem) {
        $promises[] = $browser->post(
            'https://httpbin.org/post',
            [],
            http_build_query([
                'sku' => $orderedItem->orderItemNumber,
                'amount' => $orderedItem->orderQuantity
            ])
        );
    }
    \React\Promise\all($promises)->then(
        function() use ($channel, $message) {
            $channel->ack($message);
        }
    );
};

Wait a minute ..

Further readings