summaryrefslogtreecommitdiffstats
path: root/library/X509/Scheduler.php
blob: 0963016fc30e32a3af300b6e6ab50f28897b066f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
// Icinga Web 2 X.509 Module | (c) 2018 Icinga GmbH | GPLv2

namespace Icinga\Module\X509;

use Cron\CronExpression;
use Icinga\Application\Logger;
use React\EventLoop\Factory as Loop;

class Scheduler
{
    protected $loop;

    public function __construct()
    {
        $this->loop = Loop::create();
    }

    public function add($name, $cronSchedule, callable $callback)
    {
        if (! CronExpression::isValidExpression($cronSchedule)) {
            throw new \RuntimeException('Invalid cron expression');
        }

        $now = new \DateTime();

        $expression = new CronExpression($cronSchedule);

        if ($expression->isDue($now)) {
            $this->loop->futureTick($callback);
        }

        $nextRuns = $expression->getMultipleRunDates(2, $now);

        $interval = $nextRuns[0]->getTimestamp() - $now->getTimestamp();

        $period = $nextRuns[1]->getTimestamp() - $nextRuns[0]->getTimestamp();

        Logger::info('Scheduling job %s to run at %s.', $name, $nextRuns[0]->format('Y-m-d H:i:s'));

        $loop = function () use (&$loop, $name, $callback, $period) {
            $callback();

            $nextRun = (new \DateTime())
                ->add(new \DateInterval("PT{$period}S"));

            Logger::info('Scheduling job %s to run at %s.', $name, $nextRun->format('Y-m-d H:i:s'));

            $this->loop->addTimer($period, $loop);
        };

        $this->loop->addTimer($interval, $loop);
    }

    public function run()
    {
        $this->loop->run();
    }
}