Passed
Push — v3.3 ( 1472f7 )
by Masiukevich
03:36
created

EventSourcingModule   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Test Coverage

Coverage 90%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 66
dl 0
loc 210
ccs 63
cts 70
cp 0.9
rs 10
c 3
b 0
f 0
wmc 13

9 Methods

Rating   Name   Duplication   Size   Complexity  
A withSqlStorage() 0 11 1
A registerMutexFactory() 0 6 2
A boot() 0 18 2
A registerIndexer() 0 9 1
A withCustomEventSerializer() 0 5 1
A withCustomSnapshotStrategy() 0 5 1
A registerEventSourcingProvider() 0 34 2
A registerSnapshotter() 0 19 2
A __construct() 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 1
            new Reference('service_bus.logger'),
197
        ];
198
199 1
        $containerBuilder->addDefinitions([
200 1
            EventStreamRepository::class => (new Definition(EventStreamRepository::class))->setArguments($arguments),
201 1
            EventSourcingProvider::class => (new Definition(EventSourcingProvider::class))->setArguments(
202
                [
203 1
                    new Reference(EventStreamRepository::class),
204 1
                    new Reference(MutexFactory::class),
205
                ]
206
            ),
207
        ]);
208 1
    }
209
210
    /**
211
     * @param ContainerBuilder $containerBuilder
212
     *
213
     * @return void
214
     */
215 1
    private function registerSnapshotter(ContainerBuilder $containerBuilder): void
216
    {
217 1
        if (null === $this->customSnapshotStrategyServiceId)
218
        {
219 1
            $containerBuilder->addDefinitions([
220 1
                SnapshotTrigger::class => new Definition(SnapshotVersionTrigger::class, [30]),
221
            ]);
222
223 1
            $this->customSnapshotStrategyServiceId = SnapshotTrigger::class;
224
        }
225
226
        $arguments = [
227 1
            new Reference($this->snapshotStoreServiceId),
228 1
            new Reference($this->customSnapshotStrategyServiceId),
229 1
            new Reference('service_bus.logger'),
230
        ];
231
232 1
        $containerBuilder->addDefinitions([
233 1
            Snapshotter::class => (new Definition(Snapshotter::class))->setArguments($arguments),
234
        ]);
235 1
    }
236
237
    /**
238
     * @param string $eventStoreServiceId
239
     * @param string $snapshotStoreServiceId
240
     * @param string $indexerStore
241
     */
242 1
    private function __construct(string $eventStoreServiceId, string $snapshotStoreServiceId, string $indexerStore)
243
    {
244 1
        $this->eventStoreServiceId    = $eventStoreServiceId;
245 1
        $this->snapshotStoreServiceId = $snapshotStoreServiceId;
246 1
        $this->indexerStore           = $indexerStore;
247 1
    }
248
}
249