Passed
Push — master ( b67a30...b7883b )
by Kevin
09:53 queued 08:10
created

ScheduleRunner   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 13
eloc 48
c 1
b 0
f 0
dl 0
loc 96
ccs 48
cts 48
cp 1
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A postRun() 0 11 2
A __invoke() 0 37 3
A buildSchedule() 0 5 1
A runTask() 0 12 3
A __construct() 0 5 1
A runnerFor() 0 9 3
1
<?php
2
3
namespace Zenstruck\ScheduleBundle\Schedule;
4
5
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
6
use Zenstruck\ScheduleBundle\Event\AfterScheduleEvent;
7
use Zenstruck\ScheduleBundle\Event\AfterTaskEvent;
8
use Zenstruck\ScheduleBundle\Event\BeforeScheduleEvent;
9
use Zenstruck\ScheduleBundle\Event\BeforeTaskEvent;
10
use Zenstruck\ScheduleBundle\Event\ScheduleBuildEvent;
11
use Zenstruck\ScheduleBundle\Schedule;
12
use Zenstruck\ScheduleBundle\Schedule\Exception\SkipSchedule;
13
use Zenstruck\ScheduleBundle\Schedule\Exception\SkipTask;
14
use Zenstruck\ScheduleBundle\Schedule\Extension\ExtensionHandlerRegistry;
15
use Zenstruck\ScheduleBundle\Schedule\Task\Result;
16
use Zenstruck\ScheduleBundle\Schedule\Task\TaskRunner;
17
18
/**
19
 * @author Kevin Bond <[email protected]>
20
 */
21
final class ScheduleRunner
22
{
23
    private $taskRunners;
24
    private $extensions;
25
    private $dispatcher;
26
27 38
    public function __construct(iterable $taskRunners, ExtensionHandlerRegistry $handlerRegistry, EventDispatcherInterface $dispatcher)
28
    {
29 38
        $this->taskRunners = $taskRunners;
30 38
        $this->extensions = $handlerRegistry;
31 38
        $this->dispatcher = $dispatcher;
32 38
    }
33
34 31
    public function __invoke(): AfterScheduleEvent
35
    {
36 31
        $schedule = $this->buildSchedule();
37 30
        $beforeScheduleEvent = new BeforeScheduleEvent($schedule);
38
39
        try {
40 30
            $this->dispatcher->dispatch($beforeScheduleEvent);
41 30
            $this->extensions->beforeSchedule($beforeScheduleEvent);
42 5
        } catch (SkipSchedule $e) {
43 3
            $afterScheduleEvent = AfterScheduleEvent::skip($e, $beforeScheduleEvent);
44
45 3
            $this->dispatcher->dispatch($afterScheduleEvent);
46
47 3
            return $afterScheduleEvent;
48
        }
49
50 25
        $results = [];
51
52 25
        foreach ($schedule->due() as $task) {
53 21
            $beforeTaskEvent = new BeforeTaskEvent($beforeScheduleEvent, $task);
54
55 21
            $this->dispatcher->dispatch($beforeTaskEvent);
56
57 21
            $result = $this->runTask($beforeTaskEvent);
58 21
            $afterTaskEvent = $this->postRun($beforeTaskEvent, $result);
59
60 21
            $this->dispatcher->dispatch($afterTaskEvent);
61
62 21
            $results[] = $afterTaskEvent->getResult();
63
        }
64
65 25
        $afterScheduleEvent = new AfterScheduleEvent($beforeScheduleEvent, $results);
66
67 25
        $this->extensions->afterSchedule($afterScheduleEvent);
68 25
        $this->dispatcher->dispatch($afterScheduleEvent);
69
70 25
        return $afterScheduleEvent;
71
    }
72
73 38
    public function buildSchedule(): Schedule
74
    {
75 38
        $this->dispatcher->dispatch(new ScheduleBuildEvent($schedule = new Schedule()));
76
77 37
        return $schedule;
78
    }
79
80 23
    public function runnerFor(Task $task): TaskRunner
81
    {
82 23
        foreach ($this->taskRunners as $runner) {
83 23
            if ($runner->supports($task)) {
84 20
                return $runner;
85
            }
86
        }
87
88 3
        throw new \LogicException(\sprintf('No task runner registered to handle "%s".', \get_class($task)));
89
    }
90
91 21
    private function runTask(BeforeTaskEvent $event): Result
92
    {
93 21
        $task = $event->getTask();
94
95
        try {
96 21
            $this->extensions->beforeTask($event);
97
98 20
            return $this->runnerFor($task)($task);
99 3
        } catch (SkipTask $e) {
100 1
            return $e->createResult($task);
101 2
        } catch (\Throwable $e) {
102 2
            return Result::exception($task, $e);
103
        }
104
    }
105
106 21
    private function postRun(BeforeTaskEvent $event, Result $result): AfterTaskEvent
107
    {
108 21
        $afterTaskEvent = new AfterTaskEvent($event, $result);
109
110
        try {
111 21
            $this->extensions->afterTask($afterTaskEvent);
112 1
        } catch (\Throwable $e) {
113 1
            return new AfterTaskEvent($event, Result::exception($event->getTask(), $e));
114
        }
115
116 20
        return $afterTaskEvent;
117
    }
118
}
119