Completed
Push — master ( 6b9dac...24d110 )
by Constantin
02:54
created

SagaRunner::feedSagaWithEvents()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 38
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 38
c 0
b 0
f 0
ccs 21
cts 21
cp 1
rs 8.439
cc 5
eloc 20
nc 8
nop 2
crap 5
1
<?php
2
/**
3
 * Copyright (c) 2017 Constantin Galbenu <[email protected]>
4
 */
5
6
namespace Gica\Cqrs\Saga;
7
8
9
use Gica\CodeAnalysis\MethodListenerDiscovery;
10
use Gica\CodeAnalysis\MethodListenerDiscovery\ListenerClassValidator\AnyPhpClassIsAccepted;
11
use Gica\CodeAnalysis\MethodListenerDiscovery\ListenerMethod;
12
use Gica\CodeAnalysis\Shared\ClassSorter\ByConstructorDependencySorter;
13
use Gica\Cqrs\Command\CodeAnalysis\WriteSideEventHandlerDetector;
14
use Gica\Cqrs\Event\EventWithMetaData;
15
use Gica\Cqrs\EventStore;
16
use Psr\Log\LoggerInterface;
17
18
class SagaRunner
19
{
20
21
    /**
22
     * @var EventStore
23
     */
24
    private $eventStore;
25
    /**
26
     * @var LoggerInterface
27
     */
28
    private $logger;
29
    /**
30
     * @var SagaRepository
31
     */
32
    private $sagaRepository;
33
34 2
    public function __construct(
35
        EventStore $eventStore,
36
        LoggerInterface $logger,
37
        SagaRepository $sagaRepository
38
    )
39
    {
40 2
        $this->eventStore = $eventStore;
41 2
        $this->logger = $logger;
42 2
        $this->sagaRepository = $sagaRepository;
43 2
    }
44
45 2
    public function feedSagaWithEvents($saga, ?int $afterSequence = null)
46
    {
47 2
        $discoverer = new MethodListenerDiscovery(
48 2
            new WriteSideEventHandlerDetector(),
49 2
            new AnyPhpClassIsAccepted(),
50 2
            new ByConstructorDependencySorter()
51
        );
52
53 2
        $allMethods = $discoverer->findListenerMethodsInClass(get_class($saga));
54
55 2
        $eventClasses = $this->getEventClassesFromMethods($allMethods);
56
57 2
        $this->logger->info(print_r($eventClasses, true));
58 2
        $this->logger->info("loading events...");
59
60 2
        $allEvents = $this->eventStore->loadEventsByClassNames($eventClasses);
61
62 2
        if (null !== $afterSequence) {
63 1
            $allEvents->afterSequence($afterSequence);
64
        }
65
66 2
        $this->logger->info("processing events...");
67
68 2
        foreach ($allEvents as $eventWithMetadata) {
69
            /** @var EventWithMetaData $eventWithMetadata */
70 1
            $methods = $this->findMethodsByEventClass(get_class($eventWithMetadata->getEvent()), $allMethods);
71 1
            $metaData = $eventWithMetadata->getMetaData();
72
73 1
            foreach ($methods as $method) {
74
75 1
                if (!$this->sagaRepository->isEventAlreadyDispatched(get_class($saga), $metaData->getSequence(), $metaData->getIndex())) {
76 1
                    call_user_func([$saga, $method->getMethodName()], $eventWithMetadata->getEvent(), $eventWithMetadata->getMetaData());
77
78 1
                    $this->sagaRepository->persistLastProcessedEventBySaga(get_class($saga), $metaData->getSequence(), $metaData->getIndex());
79
                }
80
            }
81
        }
82 2
    }
83
84
    /**
85
     * @param ListenerMethod[] $methods
86
     * @return array
87
     */
88 2
    private function getEventClassesFromMethods($methods)
89
    {
90 2
        $eventClasses = [];
91 2
        foreach ($methods as $listenerMethod) {
92 2
            $eventClasses[] = $listenerMethod->getEventClassName();
93
        }
94
95 2
        return $eventClasses;
96
    }
97
98
    /**
99
     * @param string $eventClass
100
     * @param ListenerMethod[] $allMethods
101
     * @return ListenerMethod[]
102
     */
103 1
    private function findMethodsByEventClass(string $eventClass, $allMethods)
104
    {
105 1
        $result = [];
106
107 1
        foreach ($allMethods as $listenerMethod) {
108 1
            if ($listenerMethod->getEventClassName() == $eventClass) {
109 1
                $result[] = $listenerMethod;
110
            }
111
        }
112
113 1
        return $result;
114
    }
115
}