Passed
Push — v3.2 ( 8a1d48...8a3142 )
by Masiukevich
01:41
created

EventSourcingModule   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 209
Duplicated Lines 0 %

Test Coverage

Coverage 89.86%

Importance

Changes 0
Metric Value
eloc 65
dl 0
loc 209
ccs 62
cts 69
cp 0.8986
rs 10
c 0
b 0
f 0
wmc 13

9 Methods

Rating   Name   Duplication   Size   Complexity  
A boot() 0 18 2
A registerIndexer() 0 9 1
A registerEventSourcingProvider() 0 33 2
A registerSnapshotter() 0 19 2
A withCustomEventSerializer() 0 5 1
A __construct() 0 5 1
A withSqlStorage() 0 11 1
A registerMutexFactory() 0 6 2
A withCustomSnapshotStrategy() 0 5 1
1
<?php
2
3
/**
4
 * Event Sourcing implementation module.
5
 *
6
 * @author  Maksim Masiukevich <[email protected]>
7
 * @license MIT
8
 * @license https://opensource.org/licenses/MIT
9
 */
10
11
declare(strict_types = 1);
12
13
namespace ServiceBus\EventSourcingModule;
14
15
use ServiceBus\Common\Module\ServiceBusModule;
16
use ServiceBus\EventSourcing\EventStream\EventStreamRepository;
17
use ServiceBus\EventSourcing\EventStream\Serializer\DefaultEventSerializer;
18
use ServiceBus\EventSourcing\EventStream\Serializer\EventSerializer;
19
use ServiceBus\EventSourcing\EventStream\Store\EventStreamStore;
20
use ServiceBus\EventSourcing\EventStream\Store\SqlEventStreamStore;
21
use ServiceBus\EventSourcing\Indexes\Store\IndexStore;
22
use ServiceBus\EventSourcing\Indexes\Store\SqlIndexStore;
23
use ServiceBus\EventSourcing\Snapshots\Snapshotter;
24
use ServiceBus\EventSourcing\Snapshots\Store\SnapshotStore;
25
use ServiceBus\EventSourcing\Snapshots\Store\SqlSnapshotStore;
26
use ServiceBus\EventSourcing\Snapshots\Triggers\SnapshotTrigger;
27
use ServiceBus\EventSourcing\Snapshots\Triggers\SnapshotVersionTrigger;
28
use ServiceBus\Mutex\InMemoryMutexFactory;
29
use ServiceBus\Mutex\MutexFactory;
30
use Symfony\Component\DependencyInjection\ContainerBuilder;
31
use Symfony\Component\DependencyInjection\Definition;
32
use Symfony\Component\DependencyInjection\Reference;
33
34
/**
35
 * @todo: custom store initialization
36
 */
37
final class EventSourcingModule implements ServiceBusModule
38
{
39
    /**
40
     * @var string
41
     */
42
    private $eventStoreServiceId;
43
44
    /**
45
     * @var string
46
     */
47
    private $snapshotStoreServiceId;
48
49
    /**
50
     * @var string
51
     */
52
    private $indexerStore;
53
54
    /**
55
     * @var string|null
56
     */
57
    private $databaseAdapterServiceId;
58
59
    /**
60
     * @var string|null
61
     */
62
    private $customEventSerializerServiceId;
63
64
    /**
65
     * @var string|null
66
     */
67
    private $customSnapshotStrategyServiceId;
68
69
    /**
70
     * @param string $databaseAdapterServiceId
71
     *
72
     * @return self
73
     */
74 1
    public static function withSqlStorage(string $databaseAdapterServiceId): self
75
    {
76 1
        $self = new self(
77 1
            EventStreamStore::class,
78 1
            SnapshotStore::class,
79 1
            IndexStore::class
80
        );
81
82 1
        $self->databaseAdapterServiceId = $databaseAdapterServiceId;
83
84 1
        return $self;
85
    }
86
87
    /**
88
     * @param string $eventSerializerServiceId
89
     *
90
     * @return $this
91
     */
92
    public function withCustomEventSerializer(string $eventSerializerServiceId): self
93
    {
94
        $this->customEventSerializerServiceId = $eventSerializerServiceId;
95
96
        return $this;
97
    }
98
99
    /**
100
     * @param string $snapshotStrategyServiceId
101
     *
102
     * @return $this
103
     */
104
    public function withCustomSnapshotStrategy(string $snapshotStrategyServiceId): self
105
    {
106
        $this->customSnapshotStrategyServiceId = $snapshotStrategyServiceId;
107
108
        return $this;
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114 1
    public function boot(ContainerBuilder $containerBuilder): void
115
    {
116
        /** Default configuration used */
117 1
        if (null !== $this->databaseAdapterServiceId)
118
        {
119 1
            $storeArguments = [new Reference($this->databaseAdapterServiceId)];
120
121 1
            $containerBuilder->addDefinitions([
122 1
                $this->eventStoreServiceId    => (new Definition(SqlEventStreamStore::class))->setArguments($storeArguments),
123 1
                $this->snapshotStoreServiceId => (new Definition(SqlSnapshotStore::class))->setArguments($storeArguments),
124 1
                $this->indexerStore           => (new Definition(SqlIndexStore::class))->setArguments($storeArguments),
125
            ]);
126
        }
127
128 1
        $this->registerMutexFactory($containerBuilder);
129 1
        $this->registerSnapshotter($containerBuilder);
130 1
        $this->registerEventSourcingProvider($containerBuilder);
131 1
        $this->registerIndexer($containerBuilder);
132 1
    }
133
134
    /**
135
     * @param ContainerBuilder $containerBuilder
136
     */
137 1
    private function registerMutexFactory(ContainerBuilder $containerBuilder): void
138
    {
139 1
        if (false === $containerBuilder->hasDefinition(MutexFactory::class))
140
        {
141 1
            $containerBuilder->addDefinitions([
142 1
                MutexFactory::class => new Definition(InMemoryMutexFactory::class),
143
            ]);
144
        }
145 1
    }
146
147
    /**
148
     * @param ContainerBuilder $containerBuilder
149
     *
150
     * @return void
151
     */
152 1
    private function registerIndexer(ContainerBuilder $containerBuilder): void
153
    {
154
        /** @psalm-suppress PossiblyNullArgument */
155 1
        $containerBuilder->addDefinitions([
156 1
            $this->indexerStore  => (new Definition(SqlIndexStore::class))->setArguments([new Reference((string) $this->databaseAdapterServiceId)]),
157 1
            IndexProvider::class => (new Definition(IndexProvider::class))->setArguments(
158
                [
159 1
                    new Reference($this->indexerStore),
160 1
                    new Reference(MutexFactory::class),
161
                ]
162
            ),
163
        ]);
164 1
    }
165
166
    /**
167
     * @param ContainerBuilder $containerBuilder
168
     *
169
     * @return void
170
     */
171 1
    private function registerEventSourcingProvider(ContainerBuilder $containerBuilder): void
172
    {
173 1
        $serializer = null;
174
175 1
        if (null !== $this->customEventSerializerServiceId)
176
        {
177
            $serializer = new Reference($this->customEventSerializerServiceId);
178
        }
179
        else
180
        {
181 1
            $containerBuilder->addDefinitions(
182
                [
183 1
                    EventSerializer::class => (new Definition(DefaultEventSerializer::class))->setArguments([
184 1
                        new Reference('service_bus.decoder.default_handler'),
185
                    ]),
186
                ]
187
            );
188
189 1
            $serializer = new Reference(EventSerializer::class);
190
        }
191
192
        $arguments = [
193 1
            new Reference($this->eventStoreServiceId),
194 1
            new Reference(Snapshotter::class),
195 1
            $serializer,
196
        ];
197
198 1
        $containerBuilder->addDefinitions([
199 1
            EventStreamRepository::class => (new Definition(EventStreamRepository::class))->setArguments($arguments),
200 1
            EventSourcingProvider::class => (new Definition(EventSourcingProvider::class))->setArguments(
201
                [
202 1
                    new Reference(EventStreamRepository::class),
203 1
                    new Reference(MutexFactory::class),
204
                ]
205
            ),
206
        ]);
207 1
    }
208
209
    /**
210
     * @param ContainerBuilder $containerBuilder
211
     *
212
     * @return void
213
     */
214 1
    private function registerSnapshotter(ContainerBuilder $containerBuilder): void
215
    {
216 1
        if (null === $this->customSnapshotStrategyServiceId)
217
        {
218 1
            $containerBuilder->addDefinitions([
219 1
                SnapshotTrigger::class => new Definition(SnapshotVersionTrigger::class),
220
            ]);
221
222 1
            $this->customSnapshotStrategyServiceId = SnapshotTrigger::class;
223
        }
224
225
        $arguments = [
226 1
            new Reference($this->snapshotStoreServiceId),
227 1
            new Reference($this->customSnapshotStrategyServiceId),
228 1
            new Reference('service_bus.logger'),
229
        ];
230
231 1
        $containerBuilder->addDefinitions([
232 1
            Snapshotter::class => (new Definition(Snapshotter::class))->setArguments($arguments),
233
        ]);
234 1
    }
235
236
    /**
237
     * @param string $eventStoreServiceId
238
     * @param string $snapshotStoreServiceId
239
     * @param string $indexerStore
240
     */
241 1
    private function __construct(string $eventStoreServiceId, string $snapshotStoreServiceId, string $indexerStore)
242
    {
243 1
        $this->eventStoreServiceId    = $eventStoreServiceId;
244 1
        $this->snapshotStoreServiceId = $snapshotStoreServiceId;
245 1
        $this->indexerStore           = $indexerStore;
246 1
    }
247
}
248