Completed
Push — master ( 5eaeb0...7eb939 )
by Wachter
11:51 queued 02:03
created

src/Task/Scheduler.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * This file is part of PHP-Task library.
4
 *
5
 * (c) php-task
6
 *
7
 * This source file is subject to the MIT license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace Task;
12
13
use Cron\CronExpression;
14
use Psr\Log\LoggerInterface;
15
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
16
use Task\Event\Events;
17
use Task\Event\TaskEvent;
18
use Task\Event\TaskFailedEvent;
19
use Task\FrequentTask\FrequentTaskInterface;
20
use Task\Handler\RegistryInterface;
21
use Task\Storage\StorageInterface;
22
23
/**
24
 * Central component which handles tasks.
25
 *
26
 * Allows to create and run tasks.
27
 *
28
 * @author Johannes Wachter <@wachterjohannes>
29
 */
30
class Scheduler implements SchedulerInterface
31
{
32
    /**
33
     * @var StorageInterface
34
     */
35
    private $storage;
36
37
    /**
38
     * @var RegistryInterface
39
     */
40
    private $registry;
41
42
    /**
43
     * @var TaskBuilderFactoryInterface
44
     */
45
    private $factory;
46
47
    /**
48
     * @var EventDispatcherInterface
49
     */
50
    private $eventDispatcher;
51
52
    /**
53
     * @var LoggerInterface
54
     */
55
    private $logger;
56
57 19
    public function __construct(
58
        StorageInterface $storage,
59
        RegistryInterface $registry,
60
        TaskBuilderFactoryInterface $factory,
61
        EventDispatcherInterface $eventDispatcher,
62
        LoggerInterface $logger = null
63
    ) {
64 19
        $this->storage = $storage;
65 19
        $this->registry = $registry;
66 19
        $this->factory = $factory;
67 19
        $this->eventDispatcher = $eventDispatcher;
68 19
        $this->logger = $logger;
69 19
    }
70
71
    /**
72
     * {@inheritdoc}
73
     */
74 9
    public function createTask($handlerName, $workload = null)
75
    {
76 9
        return $this->factory->create($this, $handlerName, $workload);
0 ignored issues
show
It seems like $workload defined by parameter $workload on line 74 can also be of type null; however, Task\TaskBuilderFactoryInterface::create() does only seem to accept string|object<Serializable>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
77
    }
78
79
    /**
80
     * {@inheritdoc}
81
     */
82 8
    public function createTaskAndSchedule($handlerName, $workload = null, $interval = null, $key = null)
83
    {
84 8
        $taskBuilder = $this->createTask($handlerName, $workload);
85
86 8
        if ($interval) {
87 4
            if (CronExpression::isValidExpression($interval)) {
88 1
                $taskBuilder->cron($interval);
89 1
            } else {
90 3
                $taskBuilder->{$interval}();
91
            }
92 4
        }
93
94 8
        if ($key) {
95 4
            $taskBuilder->setKey($key);
96 4
        }
97
98 8
        return $taskBuilder->schedule();
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104 4
    public function schedule(TaskInterface $task)
105
    {
106 4
        if (!$this->registry->has($task->getTaskName())) {
107 2
            throw new \Exception($this->getNoHandlerFoundMessage($task));
108
        }
109
110 2
        $this->storage->store($task);
111
112 2
        return $task;
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118 6
    public function run()
119
    {
120
        /** @var TaskInterface $task */
121 6
        foreach ($this->storage->findScheduled() as $task) {
122 4
            if (!$this->registry->has($task->getTaskName())) {
123
                $this->warning($this->getNoHandlerFoundMessage($task));
124
                continue;
125
            }
126
127 4
            $this->eventDispatcher->dispatch(Events::TASK_BEFORE, new TaskEvent($task));
128
129
            try {
130 4
                $result = $this->registry->run($task->getTaskName(), $task->getWorkload());
131
132 4
                $task->setResult($result);
133 4
                $task->setCompleted();
134
135 4
                $this->storage->persist($task);
136
137 4
                $this->eventDispatcher->dispatch(Events::TASK_PASSED, new TaskEvent($task));
138 4
            } catch (\Exception $ex) {
139
                // TODO set task failed. failed tasks, can be restarted by adding a flag to run command.
140
141
                $this->eventDispatcher->dispatch(Events::TASK_FAILED, new TaskFailedEvent($task, $ex));
142
143
                throw $ex;
144
            }
145
146 4
            $this->eventDispatcher->dispatch(Events::TASK_AFTER, new TaskEvent($task));
147
148
            // TODO move to event-dispatcher
149 4
            if ($task instanceof FrequentTaskInterface) {
150 2
                $task->scheduleNext($this);
151 2
            }
152 6
        }
153 6
    }
154
155
    /**
156
     * Returns message for "no handler found".
157
     *
158
     * @param TaskInterface $task
159
     *
160
     * @return string
161
     */
162 2
    private function getNoHandlerFoundMessage(TaskInterface $task)
163
    {
164 2
        return sprintf('No handler found handler for "%s" task.', $task->getTaskName());
165
    }
166
167
    /**
168
     * Write a warning into log.
169
     *
170
     * @param string $message
171
     */
172
    private function warning($message)
173
    {
174
        if (null !== $this->logger) {
175
            return;
176
        }
177
178
        $this->logger->warning($message);
179
    }
180
}
181