Skip to content

Commit

Permalink
add new example "interruptible sleep"
Browse files Browse the repository at this point in the history
Signed-off-by: Demin Yin <deminy@deminy.net>
  • Loading branch information
deminy committed Dec 14, 2023
1 parent 4ae7cb5 commit d258d81
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ docker compose exec -ti client bash # Get a Bash shell in the client container.
* [support HTTP/1, HTTP/2, and WebSocket on same port](https://github.com/deminy/swoole-by-examples/blob/master/examples/servers/mixed-protocols-1.php)
* support multiple protocols on same server
* [DDoS protection](https://github.com/deminy/swoole-by-examples/blob/master/examples/servers/ddos-protection.php): How to protect your Swoole-based application server from DDoS attacks.
* [interruptible sleep](https://github.com/deminy/swoole-by-examples/blob/master/examples/servers/interruptible-sleep.php): This example shows how to set up a cronjob in a web server, and allow the cronjob to execute at a last time when the server is shutting down.
* multiple ports listening
* client-side programming
* [HTTP/1 client](https://github.com/deminy/swoole-by-examples/blob/master/examples/clients/http1.php)
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
server:
image: deminy/swoole-by-examples:server-5.1
environment:
AUTORELOAD_PROGRAMS: "ddos-protection http1 http1-integrated http2 keepalive mixed-protocols-1 pool-msgqueue pool-tcp-socket pool-unix-socket redis rock-paper-scissors tcp1 tcp2 udp websocket websocket-integrated"
AUTORELOAD_PROGRAMS: "ddos-protection http1 http1-integrated http2 interruptible-sleep keepalive mixed-protocols-1 pool-msgqueue pool-tcp-socket pool-unix-socket redis rock-paper-scissors tcp1 tcp2 udp websocket websocket-integrated"
DISABLE_DEFAULT_SERVER: 1
ports:
- 9801:9801
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[supervisord]
user = root

[program:interruptible-sleep]
command = /var/www/servers/interruptible-sleep.php
user = root
autostart = true
autorestart = true
stdout_logfile=/proc/self/fd/1
stdout_logfile_maxbytes=0
stderr_logfile=/proc/self/fd/1
stderr_logfile_maxbytes=0
60 changes: 60 additions & 0 deletions examples/servers/interruptible-sleep.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env php
<?php

declare(strict_types=1);

/**
* In this example, we start a web server with a cronjob setup to run every 19 seconds. The cron job sends a message "[INTERRUPTIBLE-SLEEP] Simulating cronjob execution.(case 1)" to the logs of the server container when executed.
*
* The problem with traditional cronjobs is that they don't get a chance to execute at a last time before the server
* shuts down. For example, if the cronjob is scheduled to run every 19 seconds, and the server is shutting down 15
* seconds after the last cronjob execution, then the cronjob will never get a chance to execute one more time before
* the server shuts down.
*
* In this example, we use Channel to schedule a cronjob to run every 19 seconds. The implementation allows the cronjob
* to execute one more time by checking if the Channel is closed when server shuts down.
*
* When running the following command to stop and restart the server, you will see the cronjob is executed one more time
* with message "[INTERRUPTIBLE-SLEEP] Simulating cronjob execution.(case 2)" logged in the logs of the server container:
* docker compose exec -t server bash -c "supervisorctl restart interruptible-sleep"
*/

use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\Http\Server;

$exited = new Channel();
$server = new Server('0.0.0.0', 9512);

$server->on('workerStart', function (Server $server, int $workerId) use ($exited) {
if ($workerId === 0) {
Coroutine::create(function () use ($exited) {
// Here we start the second cron job that makes an HTTP request every 19 seconds.
while (true) {
echo '[INTERRUPTIBLE-SLEEP] Simulating cronjob execution. (case 1)', PHP_EOL;
$exited->pop(19);
if ($exited->errCode === SWOOLE_CHANNEL_CLOSED) {
echo '[INTERRUPTIBLE-SLEEP] Simulating cronjob execution. (case 2)', PHP_EOL;
break;
}
}
echo '[INTERRUPTIBLE-SLEEP] The cronjob has exited.', PHP_EOL;
});
}
});
$server->on('workerExit', function (Server $server, int $workerId) use ($exited) {
echo "[INTERRUPTIBLE-SLEEP] Worker #{$workerId} is exiting.", PHP_EOL;
if ($workerId === 0) {
Coroutine::create(function () use ($exited) {
$exited->close();
});
}
echo "[INTERRUPTIBLE-SLEEP] Worker #{$workerId} has exited.", PHP_EOL;
});
$server->on('request', function (Request $request, Response $response) {
$response->end('OK' . PHP_EOL);
});

$server->start();

0 comments on commit d258d81

Please sign in to comment.