add

int \Workerman\Timer::add(float $time_interval, callable $callback [,$args = array(), bool $persistent = true])

특정 함수 또는 클래스 메소드를 정기적으로 실행합니다.

주의: 타이머는 현재 프로세스 내에서 실행되며, Workerman 내에서 타이머를 실행하기 위해 새로운 프로세스나 스레드를 생성하지 않습니다.

매개변수

time_interval

얼마나 자주 실행되는지, 단위는 초이며, 소수를 지원하여 0.001까지도 가능하므로 밀리초 수준의 정밀도를 제공합니다.

callback

콜백 함수주의: 콜백 함수가 클래스의 메소드인 경우, 메소드는 public 속성이어야 합니다

args

콜백 함수의 매개변수로, 반드시 배열이어야 하며, 배열 요소는 매개변수 값입니다.

persistent

지속적인지 여부로, 한 번만 정기적으로 실행하려면 false를 전달하세요(한 번만 실행되는 작업은 완료 후 자동으로 삭제되므로 Timer::del()를 호출할 필요가 없습니다). 기본값은 true로, 계속 정기적으로 실행됩니다.

반환값

정수형을 반환하며, 이는 타이머의 timerid를 나타내며, Timer::del($timerid)를 호출하여 해당 타이머를 삭제할 수 있습니다.

예제

1. 타이머 함수가 익명 함수(클로저)인 경우

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

$task = new Worker();
// 정기 작업을 실행할 프로세스 수를 지정합니다. 비즈니스가 다중 프로세스에서 동시성 문제를 일으키지 않는지 주의합니다.
$task->count = 1;
$task->onWorkerStart = function(Worker $task)
{
    // 2.5초마다 실행
    $time_interval = 2.5;
    Timer::add($time_interval, function()
    {
        echo "작업 실행\n";
    });
};

// 워커 실행
Worker::runAll();

2. 특정 프로세스에서만 타이머 설정

하나의 워커 인스턴스에 4개의 프로세스가 있으며, id 번호가 0인 프로세스에서만 타이머를 설정합니다.

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

$worker = new Worker();
$worker->count = 4;
$worker->onWorkerStart = function(Worker $worker)
{
    // id 번호 0인 프로세스에서만 타이머를 설정하고, 다른 1, 2, 3번 프로세스는 타이머를 설정하지 않습니다.
    if($worker->id === 0)
    {
        Timer::add(1, function(){
            echo "4개의 워커 프로세스 중 0번 프로세스에서만 타이머 설정\n";
        });
    }
};
// 워커 실행
Worker::runAll();

3. 타이머 함수가 익명 함수이며, 클로저를 통해 매개변수 전달

use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$ws_worker = new Worker('websocket://0.0.0.0:8080');
$ws_worker->count = 8;
// 연결 수립 시 해당 연결에 타이머 설정
$ws_worker->onConnect = function(TcpConnection $connection)
{
    // 10초마다 실행
    $time_interval = 10;
    $connect_time = time();
    // connection 객체에 임시로 timer_id 속성을 추가하여 타이머 id를 저장
    $connection->timer_id = Timer::add($time_interval, function() use ($connection, $connect_time)
    {
         $connection->send($connect_time);
    });
};
// 연결 종료 시, 해당 연결의 타이머 삭제
$ws_worker->onClose = function(TcpConnection $connection)
{
    // 타이머 삭제
    Timer::del($connection->timer_id);
};

// 워커 실행
Worker::runAll();

4. 타이머 함수가 익명 함수이며, 타이머 인터페이스를 통해 매개변수 전달

use Workerman\Worker;
use Workerman\Timer;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';

$ws_worker = new Worker('websocket://0.0.0.0:8080');
$ws_worker->count = 8;
// 연결 수립 시 해당 연결에 타이머 설정
$ws_worker->onConnect = function(TcpConnection $connection)
{
    // 10초마다 실행
    $time_interval = 10;
    $connect_time = time();
    // connection 객체에 임시로 timer_id 속성을 추가하여 타이머 id를 저장
    $connection->timer_id = Timer::add($time_interval, function($connection, $connect_time)
    {
         $connection->send($connect_time);
    }, array($connection, $connect_time));
};
// 연결 종료 시, 해당 연결의 타이머 삭제
$ws_worker->onClose = function(TcpConnection $connection)
{
    // 타이머 삭제
    Timer::del($connection->timer_id);
};

// 워커 실행
Worker::runAll();

5. 타이머 함수가 일반 함수인 경우

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

// 일반 함수
function send_mail($to, $content)
{
    echo "메일 발송 중 ...\n";
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    $to = 'workerman@workerman.net';
    $content = 'hello workerman';
    // 10초 후 메일 발송 작업 실행, 마지막 인수에 false 전달, 단 한 번만 실행
    Timer::add(10, 'send_mail', array($to, $content), false);
};

// 워커 실행
Worker::runAll();

6. 타이머 함수가 클래스의 메소드인 경우

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

class Mail
{
    // 주의, 콜백 함수 속성은 반드시 public이어야 합니다.
    public function send($to, $content)
    {
        echo "메일 발송 중 ...\n";
    }
}

$task = new Worker();
$task->onWorkerStart = function($task)
{
    // 10초 후 한 번 메일 발송
    $mail = new Mail();
    $to = 'workerman@workerman.net';
    $content = 'hello workerman';
    Timer::add(10, array($mail, 'send'), array($to, $content), false);
};

// 워커 실행
Worker::runAll();

7. 타이머 함수가 클래스의 메소드(클래스 내부에서 타이머 사용)

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

class Mail
{
    // 주의, 콜백 함수 속성은 반드시 public이어야 합니다.
    public function send($to, $content)
    {
        echo "메일 발송 중 ...\n";
    }

    public function sendLater($to, $content)
    {
        // 콜백 메소드가 현재 클래스에 속하므로, 콜백 배열의 첫 번째 요소는 $this입니다.
        Timer::add(10, array($this, 'send'), array($to, $content), false);
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // 10초 후 한 번 메일 발송
    $mail = new Mail();
    $to = 'workerman@workerman.net';
    $content = 'hello workerman';
    $mail->sendLater($to, $content);
};

// 워커 실행
Worker::runAll();

8. 타이머 함수가 클래스의 정적 메소드인 경우

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

class Mail
{
    // 주의, 정적 메소드이며, 콜백 함수 속성도 반드시 public이어야 합니다.
    public static function send($to, $content)
    {
        echo "메일 발송 중 ...\n";
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // 10초 후 한 번 메일 발송
    $to = 'workerman@workerman.net';
    $content = 'hello workerman';
    // 클래스의 정적 메소드를 정기적으로 호출
    Timer::add(10, array('Mail', 'send'), array($to, $content), false);
};

// 워커 실행
Worker::runAll();

9. 타이머 함수가 클래스의 정적 메소드(네임스페이스 포함)

namespace Task;

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

class Mail
{
    // 주의, 정적 메소드이며, 콜백 함수 속성도 반드시 public이어야 합니다.
    public static function send($to, $content)
    {
        echo "메일 발송 중 ...\n";
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // 10초 후 한 번 메일 발송
    $to = 'workerman@workerman.net';
    $content = 'hello workerman';
    // 네임스페이스를 가진 클래스의 정적 메소드를 정기적으로 호출
    Timer::add(10, array('\Task\Mail', 'send'), array($to, $content), false);
};

// 워커 실행
Worker::runAll();

10. 타이머 내에서 현재 타이머 삭제 (use 클로저 방식으로 $timer_id 전달)

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    // 카운트
    $count = 1;
    // $timer_id가 콜백 함수 내부에서 정확하게 전달되려면, $timer_id 앞에 주소 연산자 &를 붙여야 합니다.
    $timer_id = Timer::add(1, function() use (&$timer_id, &$count)
    {
        echo "타이머 실행 $count\n";
        // 10회 실행 후 현재 타이머 삭제
        if($count++ >= 10)
        {
            echo "Timer::del($timer_id)\n";
            Timer::del($timer_id);
        }
    });
};

// 워커 실행
Worker::runAll();

11. 타이머 내에서 현재 타이머 삭제 (매개변수 방식으로 $timer_id 전달)

use Workerman\Worker;
use Workerman\Timer;
require_once __DIR__ . '/vendor/autoload.php';

class Mail
{
    public function send($to, $content, $timer_id)
    {
        // 현재 객체에 count 속성을 임시로 추가하여 타이머 실행 횟수를 기록
        $this->count = empty($this->count) ? 1 : $this->count;
        // 10회 실행 후 현재 타이머 삭제
        echo "메일 발송 {$this->count}...\n";
        if($this->count++ >= 10)
        {
            echo "Timer::del($timer_id)\n";
            Timer::del($timer_id);
        }
    }
}

$task = new Worker();
$task->onWorkerStart = function(Worker $task)
{
    $mail = new Mail();
    // $timer_id가 콜백 함수 내부에서 정확하게 전달되려면, $timer_id 앞에 주소 연산자 &를 붙여야 합니다.
    $timer_id = Timer::add(1, array($mail, 'send'), array('to', 'content', &$timer_id));
};

// 워커 실행
Worker::runAll();