Skip to content

Instantly share code, notes, and snippets.

@wangchen
Created April 22, 2014 05:33
Show Gist options
  • Save wangchen/11166325 to your computer and use it in GitHub Desktop.
Save wangchen/11166325 to your computer and use it in GitHub Desktop.
A simple swoole timer helper
<?php
error_reporting(E_ALL ^ E_NOTICE);
/**
* Timer Manager
*/
class TimerManager
{
private $_timers;
private $_timeouts;
public function __construct()
{
$this->_timers = array();
$this->_timeouts = array();
}
public function addTimer($interval, $timer_key, $callback)
{
if (!isset($this->_timers[$interval])) {
$this->_timers[$interval] = array();
}
$this->_timers[$interval][$timer_key] = $callback;
}
public function delTimer($interval, $timer_key)
{
if (isset($this->_timers[$interval])) {
unset($this->_timers[$interval][$timer_key]);
}
}
public function addTimeout($interval, $timeout_key, $callback)
{
$t = microtime(true) + $interval / 1000;
$this->_timeouts[$timeout_key] = array($t, $callback);
}
public function delTimeout($timeout_key)
{
unset($this->_timeouts[$timeout_key]);
}
public function dispatch($interval)
{
if ($interval === 1000) {
echo "enter timeout branch\n";
$t = microtime(true);
foreach ($this->_timeouts as $k => $to) {
printf("id=%d, now=%.2f threshold=%.2f\n", $k, $t, $to[0]);
if ($t > $to[0]) {
echo "timeout fired\n";
if (is_callable($to[1])) {
echo "invoke callback\n";
$to[1]();
}
unset($this->_timeouts[$k]);
}
}
}
$q = $this->_timers[$interval];
if ($q == null) {
return;
}
printf(
"timer dispatch %d, %d callbacks will be executed\n",
$interval,
count($q)
);
while ($callback = array_shift($q)) {
if (is_callable($callback)) {
$callback();
}
}
echo "leave timer\n";
}
}
// It initializes in main process and shares with any other sub-processes.
$TIMER_MGR = new TimerManager();
// The mini-version of Application
// Just for holding the object references
class Application
{
private static $_store;
private function __construct()
{
/*empty*/
}
private function __clone()
{
/*empty*/
}
public static function setObject($key, $constractor)
{
if (!isset(self::$_store)) {
self::$_store = array();
}
self::$_store[$key] = array(
'constractor' => $constractor,
'instance' => null
);
}
public static function getObject($key)
{
$entry =& self::$_store[$key]; // Here must use reference
$instance = $entry['instance'];
if (!isset($entry['instance'])) {
$instance = $entry['constractor']();
$entry['instance'] = $instance;
}
return $instance;
}
}
Application::setObject(
'timer_mgr',
function () use (&$TIMER_MGR) {
return $TIMER_MGR;
}
);
$serv = new swoole_server("0.0.0.0", 9501);
$serv->set(array(
'reactor_num' => 2,
'writer_num' => 2,
'worker_num' => 2,
'task_worker_num' => 2,
'dispatch_mode' => 2,
'max_conn' => 100000,
'max_request' => 5000,
'backlog' => 1000,
'open_cpu_affinity' => 1,
'open_tcp_nodelay' => 1,
'log_file' => '/alidata1/logs/app/swoole.log',
'daemonize' => 0,
));
$serv->on(
'Start',
function ($serv) {
printf("server started, pid=%d\n", posix_getpid());
}
);
$serv->on(
'Receive',
function (swoole_server $serv, $fd, $from_id, $data) {
echo "enter receive\n";
$data = trim($data);
$timer_mgr = Application::getObject("timer_mgr");
$uid = 1;
$timeout_key = "rest_auto::$uid"; // a business related key, eg. UID
$timer_mgr->addTimeout(5000, $timeout_key, function () use ($uid) {
// Should use swoole task to do the jobs
// Avoid using sync operations
echo "reset palyer '$uid' auto\n";
});
$serv->addtimer(1000);
echo "leave receive\n";
}
);
$serv->on(
'Task',
function (swoole_server $serv, $task_id, $from_id, $data) {
$task = Application::getObject('task');
$task->dispatch($serv, $task_id, $from_id, $data);
}
);
$serv->on(
'Finish',
function () {
echo "task finished\n";
}
);
$serv->on('WorkerStart', function ($serv, $worker_id) {
global $argv;
if ($worker_id >= $serv->setting['worker_num']) {
swoole_set_process_name("php {$argv[0]} task worker");
printf("task worker started, pid=%d\n", posix_getpid());
} else {
swoole_set_process_name("php {$argv[0]} event worker");
printf("worker started, pid=%d\n", posix_getpid());
}
});
$serv->on('Timer', function ($serv, $interval) {
echo "enter timer\n";
Application::getObject("timer_mgr")->dispatch($interval);
echo "leave timer\n";
});
$serv->start();
@wangchen
Copy link
Author

Send anything to server, a job scheduled and will be executed after 2 secs. echo 1 |nc 127.0.0.1 9501

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment