SlideShare a Scribd company logo

You Got Async in my PHP!

Web applications are becoming the norm for users, and being able to handle thousands of requests per second is happening more and more. Developers spend an enormous amount of time making sure that their applications are as fast as possible, but tuning your web server can only go so far. Async Programming is being used by many languages as a quick and easy way to serve web applications, and PHP is no exception. Libraries like ReactPHP and Amp, alongside extensions like Swoole, give developers broad choices for how to build their applications using async principles. See how these tools and async programming can help your application stay quick and agile.

1 of 140
Download to read offline
You Got Async
in my PHP!
PRESENTED BY:
Chris Tankersley
Senior PHP Developer Advocate
@dragonmantank
What is
Async?
2
It Depends
3
Procedural
Programming
4
Do this, then this, then this
$t = new Twitter(new HttpClient());
$tweets = $t->getTweets('dragonmantank');
$template = new Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
Procedural Programming
• Single Threaded
• Very susceptible to blocking
operations
• Easy to write
5
Make
Twitter
Object
Make
HTTP
Object
Get
Tweets
Read
Template
Render
Template
6
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
7
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
8
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new HttpClient()
9
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new HttpClient()
require_once 'src/HttpClient.php'
10
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new HttpClient()
11
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
12
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
13
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
getenv('TWITTER_KEY')
14
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
15
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
getenv('TWITTER_SECRET')
16
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
require_once 'src/Twitter.php'
17
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
new Twitter();
18
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
19
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
$t->getTweets()
20
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
$t->getTweets()
$httpClient->get($url)
21
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
$t->getTweets()
22
$t = new Twitter(new HttpClient());
$tweets =
$t->getTweets('dragonmantank');
$template = new
Template('tweets.php');
echo $template->render([
‘tweets’ => $tweets,
]);
script.php Call Stack
main()
23
Wait, how does
PHP avoid
blocking?
24
Wait, how does
PHP avoid
blocking?
Web Servers, like Apache,
are multi-threaded
PHP-FPM spins up
multiple threads for use
Parallel
Computing
Do this, this, and this at the same
time
$reports = [
new DailyBalance(),
new EndOfDay(),
new ProfitLossUpdate(),
];
foreach ($reports as $r) {
$pid = pcntl_fork();
if ($pid === 0) {
$r->run();
exit();
}
}
25
Parallel Programming
• Multiple Threads
• Lets the OS/CPU handle scheduling
• Can be tricky to write
26
Make
Report
Objects
Run Daily
Balance
Report Run End of
Day Report
Run
Profit-Loss
Report
End
27
Main Thread
main()
28
Main Thread
main()
foreach($report)
29
Main Thread
main()
foreach($report)
pcntl_fork()
30
Main Thread
main()
foreach($report)
pcntl_fork()
Daily Balance Thread
main()
31
Main Thread
main()
foreach($report)
pcntl_fork()
Daily Balance Thread
main()
if ($pid > 0)
if ($pid > 0)
32
Main Thread
main()
foreach($report)
pcntl_fork()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
33
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
34
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
End Of Day Thread
main()
35
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
End Of Day Thread
main()
if ($pid > 0)
if ($pid > 0)
36
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
End Of Day Thread
main()
if ($pid > 0)
$r->run()
37
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
$r->run()
38
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
39
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
$r->run()pcntl_fork()
Profit/Loss Thread
main()
40
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
if ($pid > 0)
pcntl_fork()
Profit/Loss Thread
main()
if ($pid > 0)
if ($pid > 0)
41
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
End Of Day Thread
main()
pcntl_fork()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
42
Main Thread
main()
foreach($report)
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
43
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
44
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
pcntl_wait()
45
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)
$r->run()
pcntl_wait()
46
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
if ($pid > 0)pcntl_wait()
47
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
main()
pcntl_wait()
48
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
Profit/Loss Thread
pcntl_wait()
49
Main Thread
main()
Daily Balance Thread
main()
if ($pid > 0)
$r->run()
pcntl_wait()
Async
Programming
Try and do this, this, and this, as
simultaneously as possible
$loop = EventLoop::create();
$loop->addEvent(function () {
echo "Function 1" . PHP_EOL;
return rand(1,10);
}, function($num) {
echo "Square: " . ($num * $num) .
PHP_EOL;
});
$loop->addEvent(function () {
echo "Function 2". PHP_EOL;
}, function() {
echo "Function 4" . PHP_EOL;
});
$loop->run();
50
Async Programming
• Single Threaded
• Uses an event loop
• Allows quick executions
between larger blocking
operations
51
Event loop ends
Queue
Empty?
Execute
job
Has
callback?
Add to
queue
Start Event
Loop
Yes
Yes No
No
52
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
53
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
54
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
55
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
new EventLoop()
56
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
new EventLoop()
$this->eventQueue = new SplQueue();
Event
Queue
57
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
new EventLoop()
Event
Queue
58
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
EventLoop::create()
Event
Queue
59
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
60
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
61
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event1, $callback1)
Event
Queue
62
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event1, $callback1)
$this->eventQueue->enqueue([
$event1, $callback1
]);
Event
Queue
$event1
63
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event1, $callback1)
Event
Queue
$event1
64
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1
65
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1
66
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event2, $callback2)
Event
Queue
$event1
67
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event2, $callback2)
$this->eventQueue->enqueue([
$event2, $callback2
]);
Event
Queue
$event1 $event2
68
$loop = EventLoop::create();
$loop->addEvent($event1, $callback2);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
addEvent($event2, $callback2)
Event
Queue
$event1 $event2
69
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1 $event2
70
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
Event
Queue
$event1 $event2
71
Call Stack
main()
run()
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
Event
Queue
$event1 $event2
72
Call Stack
main()
run()
foreach ($this->eventQueue as $event)
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
echo "Function 1" . PHP_EOL;
return rand(1,10);
$event[0]
Event
Queue
$event2
73
Call Stack
main()
run()
foreach ($this->eventQueue as $event)
$return = $event[0]()
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
echo "Function 1" . PHP_EOL;
return rand(1,10);
$event[0]
Event
Queue
$event2
74
Call Stack
main()
run()
foreach ($this->eventQueue as $event)
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php
5
$return
Event
Queue
$event2
75
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
5
$return
Event
Queue
$event2
76
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
5
$return
$this->addEvent($wrappedCallback)
Event
Queue
$event2 $callback1
77
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
5
$return
Event
Queue
$event2 $callback1
78
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
79
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
80
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
echo
81
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
82
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
83
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
return void
84
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
echo "Function 2". PHP_EOL;
$event[0]
Event
Queue
$callback1
$return = $event[0]()
85
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
void
$return
Event
Queue
$callback1
if (!is_null($event[1]))
86
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
void
$return
$this->addEvent($wrappedCallback)
Event
Queue
$callback1 $callback2
87
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
if (!is_null($event[1]))
void
$return
Event
Queue
$callback1 $callback2
88
$loop = EventLoop::create();
$loop->addEvent($event1, $callback1);
$loop->addEvent($event2, $callback2);
$loop->run();
eventloop.php Call Stack
main()
run()
foreach ($this->eventQueue as $event)
void
$return
Event
Queue
$callback1 $callback2
89
Most Async is
just Event Loop
Programming
It is a different way to structure
your program
90
Most Async is
just Event Loop
Programming
It is a different way to structure
your program
Async is not:
• Concurrent
• Non-Blocking
• Multi-threaded
• Magic
Async can help better structure
your logic
91
Async makes you think about
end results, not order of
operations
92
Async
Concepts
in PHP
93
Event Loops
Adding In The Special Sauce
94
Async Programming
95
Event loop ends
Queue
Empty?
Execute
job
Has
callback?
Add to
queue
Start Event
Loop
Yes
Yes No
No
Async Programming
96
Event loop ends
Queue
Empty?
Execute
job
Has
callback?
Add to
queue
Start Event
Loop
Yes
Yes No
No
Event Loops
ReactPHP
97
98
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
99
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
100
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
101
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
102
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
103
$loop = Factory::create();
$server = new Server(function (ServerRequestInterface $request) {
return new Response(
200,
array(
'Content-Type' => 'text/plain'
),
"Hello worldn"
);
});
$socket = new ReactSocketServer(
isset($argv[1]) ? $argv[1] : '0.0.0.0:0',
$loop
);
$server->listen($socket);
echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) .
PHP_EOL;
$loop->run();
104
RatchetPHP
105
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
106
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
107
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
108
$socket = new Socket();
$ws = new WsServer($socket);
$ws->setStrictSubProtocolCheck(false);
$server = new App('localhost', '8080', '0.0.0.0');
$server->routes->add(
'events',
new Route('/events', array('_controller' => new EventsController()))
);
$server->routes->add(
'onAnswer',
new Route('/onAnswer', array('_controller' => new AnswerController()))
);
$server->routes->add(
'socket',
new Route('/socket', array('_controller' => $ws))
);
$server->run();
109
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
110
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
111
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
112
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
113
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
114
public function onMessage(RatchetConnectionInterface $from, $msg)
{
$event = json_decode($msg, true);
if($event) {
switch($event['event']) {
case 'websocket:dtmf':
try {
$uuid = $this->calls[$from->resourceId];
$talk = $this->nexmo->calls()->get(
new Call($uuid)
)
->talk();
$talk->setText('You pressed ' . $event['digit']);
$talk->put();
break;
} catch (Exception $e) {
var_dump('Error: ' . $e->getMessage());
}
break;
}
} else {
file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY);
}
}
Promises
Pretty wrappers for callbacks
115
Callback Hell
116
Russian Nesting Doll of Sadness
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
117
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
118
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
119
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}, function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
120
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}), function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
121
Callbacks Being Passed To More Callbacks
$activeFloridaUsers = array_filter(
array_filter(
array_filter($users, function($user) {
return $user->accountActive();
}), function($user) {
return $user->getBalance() > 0;
}), function($user) {
return $user->getState() === "FL";
}
));
122
What do Promises provide?
123
• Built off of Promises/A+
• A cleaner interface for callbacks
• A more structured workflow for one logic block to the next
• A way to handle errors in a clean manner
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
124
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
125
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
126
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->resolve();
127
A Cleaner
Callback
Interface
use GuzzleHttpPromisePromise;
$fulfilled = function ($value) {
echo 'The promise was fulfilled.';
};
$rejected = function ($reason) {
echo 'The promise was rejected.';
};
$promise = new Promise();
$promise->then($fulfilled, $rejected);
$promise->then($fulfilled2, $rejected2);
$promise->resolve();
128
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
129
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
130
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
131
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
132
$promise = new Promise();
$promise->then(function ($users) {
return array_filter($users, function($user) {
return $user->accountActive();
});
});
$promise->then(function ($activeUsers) {
return array_filter($activeUsers, function($user) {
return $user->getBalance() > 0;
});
});
$promise->then(function ($usersWithBalance) {
return array_filter($usersWithBalance, function($user) {
return $user->getState() === 'FL';
});
});
133
$promise->resolve($users);
$activeFLUsers = $promise->wait();
134
Getting the Values
$promise->resolve($users);
$activeFLUsers = $promise->wait();
135
Getting the Values
Additional
Takeaways
136
Worker/Queues
137
Horizontally scale work
VONAGE CONFIDENTIAL
Generators and Coroutines
yielding Control Back to the Event Loop
138
Swoole
Like PHP-FPM but has coroutines
139
140
Chris Tankersley
Senior PHP Developer Advocate
at Nexmo
@dragonmantank
chris@ctankersley.com

Recommended

PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)PHP 7 – What changed internally? (Forum PHP 2015)
PHP 7 – What changed internally? (Forum PHP 2015)Nikita Popov
 
An Elephant of a Different Colour: Hack
An Elephant of a Different Colour: HackAn Elephant of a Different Colour: Hack
An Elephant of a Different Colour: HackVic Metcalfe
 
R57shell
R57shellR57shell
R57shellady36
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
PHP 7 – What changed internally?
PHP 7 – What changed internally?PHP 7 – What changed internally?
PHP 7 – What changed internally?Nikita Popov
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixturesBill Chang
 

More Related Content

What's hot

Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
循環参照のはなし
循環参照のはなし循環参照のはなし
循環参照のはなしMasahiro Honma
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsMark Baker
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionIan Barber
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm OldRoss Tuck
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8XSolve
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersIan Barber
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6garux
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks Damien Seguy
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterRicardo Signes
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPatrick Allaert
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 

What's hot (20)

Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
循環参照のはなし
循環参照のはなし循環参照のはなし
循環参照のはなし
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
Debugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 VersionDebugging: Rules And Tools - PHPTek 11 Version
Debugging: Rules And Tools - PHPTek 11 Version
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8Xlab #1: Advantages of functional programming in Java 8
Xlab #1: Advantages of functional programming in Java 8
 
Teaching Your Machine To Find Fraudsters
Teaching Your Machine To Find FraudstersTeaching Your Machine To Find Fraudsters
Teaching Your Machine To Find Fraudsters
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Introdução ao Perl 6
Introdução ao Perl 6Introdução ao Perl 6
Introdução ao Perl 6
 
PHP tips and tricks
PHP tips and tricks PHP tips and tricks
PHP tips and tricks
 
Crafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::ExporterCrafting Custom Interfaces with Sub::Exporter
Crafting Custom Interfaces with Sub::Exporter
 
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, ItalyPHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
PHP data structures (and the impact of php 7 on them), phpDay Verona 2015, Italy
 
Inc
IncInc
Inc
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 

Similar to You Got Async in my PHP!

WordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixWordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixMark Jaquith
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011Alessandro Nadalin
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2Elizabeth Smith
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of TransductionDavid Stockton
 
Grok Drupal (7) Theming
Grok Drupal (7) ThemingGrok Drupal (7) Theming
Grok Drupal (7) ThemingPINGV
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11Combell NV
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128PrinceGuru MS
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Twig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPTwig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPFabien Potencier
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Shinya Ohyanagi
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 

Similar to You Got Async in my PHP! (20)

PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
 
2013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 22013 - Benjamin Eberlei - Doctrine 2
2013 - Benjamin Eberlei - Doctrine 2
 
WordPress Security - WordCamp Phoenix
WordPress Security - WordCamp PhoenixWordPress Security - WordCamp Phoenix
WordPress Security - WordCamp Phoenix
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2
 
PHP Tutorial (funtion)
PHP Tutorial (funtion)PHP Tutorial (funtion)
PHP Tutorial (funtion)
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
 
Intermediate PHP
Intermediate PHPIntermediate PHP
Intermediate PHP
 
Grok Drupal (7) Theming
Grok Drupal (7) ThemingGrok Drupal (7) Theming
Grok Drupal (7) Theming
 
CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11CLI, the other SAPI phpnw11
CLI, the other SAPI phpnw11
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Twig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHPTwig, the flexible, fast, and secure template language for PHP
Twig, the flexible, fast, and secure template language for PHP
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 

More from Chris Tankersley

Docker is Dead: Long Live Containers
Docker is Dead: Long Live ContainersDocker is Dead: Long Live Containers
Docker is Dead: Long Live ContainersChris Tankersley
 
Bend time to your will with git
Bend time to your will with gitBend time to your will with git
Bend time to your will with gitChris Tankersley
 
Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)Chris Tankersley
 
Dead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPIDead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPIChris Tankersley
 
Killer Docker Workflows for Development
Killer Docker Workflows for DevelopmentKiller Docker Workflows for Development
Killer Docker Workflows for DevelopmentChris Tankersley
 
Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Chris Tankersley
 
BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018Chris Tankersley
 
You Were Lied To About Optimization
You Were Lied To About OptimizationYou Were Lied To About Optimization
You Were Lied To About OptimizationChris Tankersley
 
Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017Chris Tankersley
 
Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017Chris Tankersley
 
Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Chris Tankersley
 
Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Chris Tankersley
 
OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017Chris Tankersley
 
From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017Chris Tankersley
 
Docker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPDocker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPChris Tankersley
 
Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016Chris Tankersley
 
How We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open SourceHow We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open SourceChris Tankersley
 
Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Chris Tankersley
 

More from Chris Tankersley (20)

Docker is Dead: Long Live Containers
Docker is Dead: Long Live ContainersDocker is Dead: Long Live Containers
Docker is Dead: Long Live Containers
 
Bend time to your will with git
Bend time to your will with gitBend time to your will with git
Bend time to your will with git
 
Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)Using PHP Functions! (Not those functions, Google Cloud Functions)
Using PHP Functions! (Not those functions, Google Cloud Functions)
 
Dead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPIDead Simple APIs with OpenAPI
Dead Simple APIs with OpenAPI
 
Killer Docker Workflows for Development
Killer Docker Workflows for DevelopmentKiller Docker Workflows for Development
Killer Docker Workflows for Development
 
Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018Docker for Developers - PHP Detroit 2018
Docker for Developers - PHP Detroit 2018
 
Docker for Developers
Docker for DevelopersDocker for Developers
Docker for Developers
 
They are Watching You
They are Watching YouThey are Watching You
They are Watching You
 
BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018BASHing at the CLI - Midwest PHP 2018
BASHing at the CLI - Midwest PHP 2018
 
You Were Lied To About Optimization
You Were Lied To About OptimizationYou Were Lied To About Optimization
You Were Lied To About Optimization
 
Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017Docker for PHP Developers - php[world] 2017
Docker for PHP Developers - php[world] 2017
 
Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017Docker for PHP Developers - Madison PHP 2017
Docker for PHP Developers - Madison PHP 2017
 
Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017Docker for Developers - php[tek] 2017
Docker for Developers - php[tek] 2017
 
Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017Why Docker? Dayton PHP, April 2017
Why Docker? Dayton PHP, April 2017
 
OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017OOP Is More Then Cars and Dogs - Midwest PHP 2017
OOP Is More Then Cars and Dogs - Midwest PHP 2017
 
From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017From Docker to Production - SunshinePHP 2017
From Docker to Production - SunshinePHP 2017
 
Docker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHPDocker for Developers - Sunshine PHP
Docker for Developers - Sunshine PHP
 
Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016Coming to Terms with OOP In Drupal - php[world] 2016
Coming to Terms with OOP In Drupal - php[world] 2016
 
How We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open SourceHow We Got Here: A Brief History of Open Source
How We Got Here: A Brief History of Open Source
 
Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016Docker for PHP Developers - ZendCon 2016
Docker for PHP Developers - ZendCon 2016
 

Recently uploaded

CloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlue
CloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlueCloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlue
CloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlueShapeBlue
 
Low Latency at Extreme Scale: Proven Practices & Pitfalls
Low Latency at Extreme Scale: Proven Practices & PitfallsLow Latency at Extreme Scale: Proven Practices & Pitfalls
Low Latency at Extreme Scale: Proven Practices & PitfallsScyllaDB
 
iOncologi_Pitch Deck_2024 slide show for hostinger
iOncologi_Pitch Deck_2024 slide show for hostingeriOncologi_Pitch Deck_2024 slide show for hostinger
iOncologi_Pitch Deck_2024 slide show for hostingerssuser9354ce
 
AMER Introduction to ThousandEyes Webinar
AMER Introduction to ThousandEyes WebinarAMER Introduction to ThousandEyes Webinar
AMER Introduction to ThousandEyes WebinarThousandEyes
 
CloudStack Authentication Methods – Harikrishna Patnala, ShapeBlue
CloudStack Authentication Methods – Harikrishna Patnala, ShapeBlueCloudStack Authentication Methods – Harikrishna Patnala, ShapeBlue
CloudStack Authentication Methods – Harikrishna Patnala, ShapeBlueShapeBlue
 
VM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlue
VM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlueVM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlue
VM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlueShapeBlue
 
Geospatial Synergy: Amplifying Efficiency with FME & Esri
Geospatial Synergy: Amplifying Efficiency with FME & EsriGeospatial Synergy: Amplifying Efficiency with FME & Esri
Geospatial Synergy: Amplifying Efficiency with FME & EsriSafe Software
 
Python For Kids - Sách Lập trình cho trẻ em
Python For Kids - Sách Lập trình cho trẻ emPython For Kids - Sách Lập trình cho trẻ em
Python For Kids - Sách Lập trình cho trẻ emNho Vĩnh
 
Why Disability Justice should be at the core of your digital accessibility jo...
Why Disability Justice should be at the core of your digital accessibility jo...Why Disability Justice should be at the core of your digital accessibility jo...
Why Disability Justice should be at the core of your digital accessibility jo...Modality Co
 
Achieving Excellence IESVE for HVAC Simulation.pdf
Achieving Excellence IESVE for HVAC Simulation.pdfAchieving Excellence IESVE for HVAC Simulation.pdf
Achieving Excellence IESVE for HVAC Simulation.pdfIES VE
 
Key projects in AI, ML and Generative AI
Key projects in AI, ML and Generative AIKey projects in AI, ML and Generative AI
Key projects in AI, ML and Generative AIVijayananda Mohire
 
Mastering Play Store App Listing and Optimization
Mastering Play Store App Listing and OptimizationMastering Play Store App Listing and Optimization
Mastering Play Store App Listing and OptimizationAppsthentic Technology
 
Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)
Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)
Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)François
 
How We Grew Up with CloudStack and its Journey – Dilip Singh, DataHub
How We Grew Up with CloudStack and its Journey – Dilip Singh, DataHubHow We Grew Up with CloudStack and its Journey – Dilip Singh, DataHub
How We Grew Up with CloudStack and its Journey – Dilip Singh, DataHubShapeBlue
 
Artificial Intelligence - AI For Everyone
Artificial Intelligence - AI For EveryoneArtificial Intelligence - AI For Everyone
Artificial Intelligence - AI For EveryoneSridhar Seshadri
 
National Institute of Standards and Technology (NIST) Cybersecurity Framework...
National Institute of Standards and Technology (NIST) Cybersecurity Framework...National Institute of Standards and Technology (NIST) Cybersecurity Framework...
National Institute of Standards and Technology (NIST) Cybersecurity Framework...MichaelBenis1
 
Q4 2023 Quarterly Investor Presentation - FINAL.pdf
Q4 2023 Quarterly Investor Presentation - FINAL.pdfQ4 2023 Quarterly Investor Presentation - FINAL.pdf
Q4 2023 Quarterly Investor Presentation - FINAL.pdfTejal81
 
Communities, networking and developer culture
Communities, networking and developer cultureCommunities, networking and developer culture
Communities, networking and developer cultureRavi Sanghani
 
New ThousandEyes Product Features and Release Highlights: February 2024
New ThousandEyes Product Features and Release Highlights: February 2024New ThousandEyes Product Features and Release Highlights: February 2024
New ThousandEyes Product Features and Release Highlights: February 2024ThousandEyes
 

Recently uploaded (20)

Sue Loth: Job Search Strategies using personal connections
Sue Loth: Job Search Strategies using personal connectionsSue Loth: Job Search Strategies using personal connections
Sue Loth: Job Search Strategies using personal connections
 
CloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlue
CloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlueCloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlue
CloudStack Tooling Ecosystem – Kiran Chavala, ShapeBlue
 
Low Latency at Extreme Scale: Proven Practices & Pitfalls
Low Latency at Extreme Scale: Proven Practices & PitfallsLow Latency at Extreme Scale: Proven Practices & Pitfalls
Low Latency at Extreme Scale: Proven Practices & Pitfalls
 
iOncologi_Pitch Deck_2024 slide show for hostinger
iOncologi_Pitch Deck_2024 slide show for hostingeriOncologi_Pitch Deck_2024 slide show for hostinger
iOncologi_Pitch Deck_2024 slide show for hostinger
 
AMER Introduction to ThousandEyes Webinar
AMER Introduction to ThousandEyes WebinarAMER Introduction to ThousandEyes Webinar
AMER Introduction to ThousandEyes Webinar
 
CloudStack Authentication Methods – Harikrishna Patnala, ShapeBlue
CloudStack Authentication Methods – Harikrishna Patnala, ShapeBlueCloudStack Authentication Methods – Harikrishna Patnala, ShapeBlue
CloudStack Authentication Methods – Harikrishna Patnala, ShapeBlue
 
VM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlue
VM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlueVM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlue
VM Migration from VMware to CloudStack and KVM – Suresh Anaparti, ShapeBlue
 
Geospatial Synergy: Amplifying Efficiency with FME & Esri
Geospatial Synergy: Amplifying Efficiency with FME & EsriGeospatial Synergy: Amplifying Efficiency with FME & Esri
Geospatial Synergy: Amplifying Efficiency with FME & Esri
 
Python For Kids - Sách Lập trình cho trẻ em
Python For Kids - Sách Lập trình cho trẻ emPython For Kids - Sách Lập trình cho trẻ em
Python For Kids - Sách Lập trình cho trẻ em
 
Why Disability Justice should be at the core of your digital accessibility jo...
Why Disability Justice should be at the core of your digital accessibility jo...Why Disability Justice should be at the core of your digital accessibility jo...
Why Disability Justice should be at the core of your digital accessibility jo...
 
Achieving Excellence IESVE for HVAC Simulation.pdf
Achieving Excellence IESVE for HVAC Simulation.pdfAchieving Excellence IESVE for HVAC Simulation.pdf
Achieving Excellence IESVE for HVAC Simulation.pdf
 
Key projects in AI, ML and Generative AI
Key projects in AI, ML and Generative AIKey projects in AI, ML and Generative AI
Key projects in AI, ML and Generative AI
 
Mastering Play Store App Listing and Optimization
Mastering Play Store App Listing and OptimizationMastering Play Store App Listing and Optimization
Mastering Play Store App Listing and Optimization
 
Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)
Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)
Mind your App Footprint 🐾⚡️🌱 (@FlutterHeroes 2024)
 
How We Grew Up with CloudStack and its Journey – Dilip Singh, DataHub
How We Grew Up with CloudStack and its Journey – Dilip Singh, DataHubHow We Grew Up with CloudStack and its Journey – Dilip Singh, DataHub
How We Grew Up with CloudStack and its Journey – Dilip Singh, DataHub
 
Artificial Intelligence - AI For Everyone
Artificial Intelligence - AI For EveryoneArtificial Intelligence - AI For Everyone
Artificial Intelligence - AI For Everyone
 
National Institute of Standards and Technology (NIST) Cybersecurity Framework...
National Institute of Standards and Technology (NIST) Cybersecurity Framework...National Institute of Standards and Technology (NIST) Cybersecurity Framework...
National Institute of Standards and Technology (NIST) Cybersecurity Framework...
 
Q4 2023 Quarterly Investor Presentation - FINAL.pdf
Q4 2023 Quarterly Investor Presentation - FINAL.pdfQ4 2023 Quarterly Investor Presentation - FINAL.pdf
Q4 2023 Quarterly Investor Presentation - FINAL.pdf
 
Communities, networking and developer culture
Communities, networking and developer cultureCommunities, networking and developer culture
Communities, networking and developer culture
 
New ThousandEyes Product Features and Release Highlights: February 2024
New ThousandEyes Product Features and Release Highlights: February 2024New ThousandEyes Product Features and Release Highlights: February 2024
New ThousandEyes Product Features and Release Highlights: February 2024
 

You Got Async in my PHP!

  • 1. You Got Async in my PHP! PRESENTED BY: Chris Tankersley Senior PHP Developer Advocate @dragonmantank
  • 4. Procedural Programming 4 Do this, then this, then this $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]);
  • 5. Procedural Programming • Single Threaded • Very susceptible to blocking operations • Easy to write 5 Make Twitter Object Make HTTP Object Get Tweets Read Template Render Template
  • 6. 6 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack
  • 7. 7 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main()
  • 8. 8 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new HttpClient()
  • 9. 9 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new HttpClient() require_once 'src/HttpClient.php'
  • 10. 10 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new HttpClient()
  • 11. 11 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter();
  • 12. 12 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php'
  • 13. 13 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php' getenv('TWITTER_KEY')
  • 14. 14 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php'
  • 15. 15 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php' getenv('TWITTER_SECRET')
  • 16. 16 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter(); require_once 'src/Twitter.php'
  • 17. 17 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() new Twitter();
  • 18. 18 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main()
  • 19. 19 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() $t->getTweets()
  • 20. 20 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() $t->getTweets() $httpClient->get($url)
  • 21. 21 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main() $t->getTweets()
  • 22. 22 $t = new Twitter(new HttpClient()); $tweets = $t->getTweets('dragonmantank'); $template = new Template('tweets.php'); echo $template->render([ ‘tweets’ => $tweets, ]); script.php Call Stack main()
  • 23. 23 Wait, how does PHP avoid blocking?
  • 24. 24 Wait, how does PHP avoid blocking? Web Servers, like Apache, are multi-threaded PHP-FPM spins up multiple threads for use
  • 25. Parallel Computing Do this, this, and this at the same time $reports = [ new DailyBalance(), new EndOfDay(), new ProfitLossUpdate(), ]; foreach ($reports as $r) { $pid = pcntl_fork(); if ($pid === 0) { $r->run(); exit(); } } 25
  • 26. Parallel Programming • Multiple Threads • Lets the OS/CPU handle scheduling • Can be tricky to write 26 Make Report Objects Run Daily Balance Report Run End of Day Report Run Profit-Loss Report End
  • 31. 31 Main Thread main() foreach($report) pcntl_fork() Daily Balance Thread main() if ($pid > 0) if ($pid > 0)
  • 33. 33 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()
  • 34. 34 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()pcntl_fork() End Of Day Thread main()
  • 35. 35 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()pcntl_fork() End Of Day Thread main() if ($pid > 0) if ($pid > 0)
  • 36. 36 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run()pcntl_fork() End Of Day Thread main() if ($pid > 0) $r->run()
  • 37. 37 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) $r->run()
  • 38. 38 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) $r->run()pcntl_fork()
  • 39. 39 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) $r->run()pcntl_fork() Profit/Loss Thread main()
  • 40. 40 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() if ($pid > 0) pcntl_fork() Profit/Loss Thread main() if ($pid > 0) if ($pid > 0)
  • 41. 41 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() End Of Day Thread main() pcntl_fork() Profit/Loss Thread main() if ($pid > 0) $r->run()
  • 42. 42 Main Thread main() foreach($report) Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run()
  • 43. 43 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run()
  • 44. 44 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run() pcntl_wait()
  • 45. 45 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0) $r->run() pcntl_wait()
  • 46. 46 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() if ($pid > 0)pcntl_wait()
  • 47. 47 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread main() pcntl_wait()
  • 48. 48 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() Profit/Loss Thread pcntl_wait()
  • 49. 49 Main Thread main() Daily Balance Thread main() if ($pid > 0) $r->run() pcntl_wait()
  • 50. Async Programming Try and do this, this, and this, as simultaneously as possible $loop = EventLoop::create(); $loop->addEvent(function () { echo "Function 1" . PHP_EOL; return rand(1,10); }, function($num) { echo "Square: " . ($num * $num) . PHP_EOL; }); $loop->addEvent(function () { echo "Function 2". PHP_EOL; }, function() { echo "Function 4" . PHP_EOL; }); $loop->run(); 50
  • 51. Async Programming • Single Threaded • Uses an event loop • Allows quick executions between larger blocking operations 51 Event loop ends Queue Empty? Execute job Has callback? Add to queue Start Event Loop Yes Yes No No
  • 52. 52 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main()
  • 53. 53 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main()
  • 54. 54 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create()
  • 55. 55 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() new EventLoop()
  • 56. 56 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() new EventLoop() $this->eventQueue = new SplQueue(); Event Queue
  • 57. 57 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() new EventLoop() Event Queue
  • 58. 58 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() EventLoop::create() Event Queue
  • 59. 59 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue
  • 60. 60 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue
  • 61. 61 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event1, $callback1) Event Queue
  • 62. 62 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event1, $callback1) $this->eventQueue->enqueue([ $event1, $callback1 ]); Event Queue $event1
  • 63. 63 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event1, $callback1) Event Queue $event1
  • 64. 64 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1
  • 65. 65 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1
  • 66. 66 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event2, $callback2) Event Queue $event1
  • 67. 67 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event2, $callback2) $this->eventQueue->enqueue([ $event2, $callback2 ]); Event Queue $event1 $event2
  • 68. 68 $loop = EventLoop::create(); $loop->addEvent($event1, $callback2); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() addEvent($event2, $callback2) Event Queue $event1 $event2
  • 69. 69 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1 $event2
  • 70. 70 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() Event Queue $event1 $event2
  • 71. 71 Call Stack main() run() $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Event Queue $event1 $event2
  • 72. 72 Call Stack main() run() foreach ($this->eventQueue as $event) $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php echo "Function 1" . PHP_EOL; return rand(1,10); $event[0] Event Queue $event2
  • 73. 73 Call Stack main() run() foreach ($this->eventQueue as $event) $return = $event[0]() $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php echo "Function 1" . PHP_EOL; return rand(1,10); $event[0] Event Queue $event2
  • 74. 74 Call Stack main() run() foreach ($this->eventQueue as $event) $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php 5 $return Event Queue $event2
  • 75. 75 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) 5 $return Event Queue $event2
  • 76. 76 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) 5 $return $this->addEvent($wrappedCallback) Event Queue $event2 $callback1
  • 77. 77 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) 5 $return Event Queue $event2 $callback1
  • 78. 78 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1
  • 79. 79 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 80. 80 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]() echo
  • 81. 81 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 82. 82 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 83. 83 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]() return void
  • 84. 84 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) echo "Function 2". PHP_EOL; $event[0] Event Queue $callback1 $return = $event[0]()
  • 85. 85 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) void $return Event Queue $callback1 if (!is_null($event[1]))
  • 86. 86 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) void $return $this->addEvent($wrappedCallback) Event Queue $callback1 $callback2
  • 87. 87 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) if (!is_null($event[1])) void $return Event Queue $callback1 $callback2
  • 88. 88 $loop = EventLoop::create(); $loop->addEvent($event1, $callback1); $loop->addEvent($event2, $callback2); $loop->run(); eventloop.php Call Stack main() run() foreach ($this->eventQueue as $event) void $return Event Queue $callback1 $callback2
  • 89. 89 Most Async is just Event Loop Programming It is a different way to structure your program
  • 90. 90 Most Async is just Event Loop Programming It is a different way to structure your program Async is not: • Concurrent • Non-Blocking • Multi-threaded • Magic
  • 91. Async can help better structure your logic 91
  • 92. Async makes you think about end results, not order of operations 92
  • 94. Event Loops Adding In The Special Sauce 94
  • 95. Async Programming 95 Event loop ends Queue Empty? Execute job Has callback? Add to queue Start Event Loop Yes Yes No No
  • 96. Async Programming 96 Event loop ends Queue Empty? Execute job Has callback? Add to queue Start Event Loop Yes Yes No No Event Loops
  • 98. 98 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 99. 99 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 100. 100 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 101. 101 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 102. 102 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 103. 103 $loop = Factory::create(); $server = new Server(function (ServerRequestInterface $request) { return new Response( 200, array( 'Content-Type' => 'text/plain' ), "Hello worldn" ); }); $socket = new ReactSocketServer( isset($argv[1]) ? $argv[1] : '0.0.0.0:0', $loop ); $server->listen($socket); echo 'Listening on ' . str_replace('tcp:', 'http:', $socket->getAddress()) . PHP_EOL; $loop->run();
  • 105. 105 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 106. 106 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 107. 107 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 108. 108 $socket = new Socket(); $ws = new WsServer($socket); $ws->setStrictSubProtocolCheck(false); $server = new App('localhost', '8080', '0.0.0.0'); $server->routes->add( 'events', new Route('/events', array('_controller' => new EventsController())) ); $server->routes->add( 'onAnswer', new Route('/onAnswer', array('_controller' => new AnswerController())) ); $server->routes->add( 'socket', new Route('/socket', array('_controller' => $ws)) ); $server->run();
  • 109. 109 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 110. 110 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 111. 111 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 112. 112 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 113. 113 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 114. 114 public function onMessage(RatchetConnectionInterface $from, $msg) { $event = json_decode($msg, true); if($event) { switch($event['event']) { case 'websocket:dtmf': try { $uuid = $this->calls[$from->resourceId]; $talk = $this->nexmo->calls()->get( new Call($uuid) ) ->talk(); $talk->setText('You pressed ' . $event['digit']); $talk->put(); break; } catch (Exception $e) { var_dump('Error: ' . $e->getMessage()); } break; } } else { file_put_contents('./sample.wav', $msg, FILE_APPEND | FILE_BINARY); } }
  • 117. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 117
  • 118. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 118
  • 119. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 119
  • 120. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }, function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 120
  • 121. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }), function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 121
  • 122. Callbacks Being Passed To More Callbacks $activeFloridaUsers = array_filter( array_filter( array_filter($users, function($user) { return $user->accountActive(); }), function($user) { return $user->getBalance() > 0; }), function($user) { return $user->getState() === "FL"; } )); 122
  • 123. What do Promises provide? 123 • Built off of Promises/A+ • A cleaner interface for callbacks • A more structured workflow for one logic block to the next • A way to handle errors in a clean manner
  • 124. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 124
  • 125. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 125
  • 126. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 126
  • 127. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->resolve(); 127
  • 128. A Cleaner Callback Interface use GuzzleHttpPromisePromise; $fulfilled = function ($value) { echo 'The promise was fulfilled.'; }; $rejected = function ($reason) { echo 'The promise was rejected.'; }; $promise = new Promise(); $promise->then($fulfilled, $rejected); $promise->then($fulfilled2, $rejected2); $promise->resolve(); 128
  • 129. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 129
  • 130. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 130
  • 131. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 131
  • 132. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 132
  • 133. $promise = new Promise(); $promise->then(function ($users) { return array_filter($users, function($user) { return $user->accountActive(); }); }); $promise->then(function ($activeUsers) { return array_filter($activeUsers, function($user) { return $user->getBalance() > 0; }); }); $promise->then(function ($usersWithBalance) { return array_filter($usersWithBalance, function($user) { return $user->getState() === 'FL'; }); }); 133
  • 138. VONAGE CONFIDENTIAL Generators and Coroutines yielding Control Back to the Event Loop 138
  • 139. Swoole Like PHP-FPM but has coroutines 139
  • 140. 140 Chris Tankersley Senior PHP Developer Advocate at Nexmo @dragonmantank chris@ctankersley.com