EventSourcingModule   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Test Coverage

Coverage 90%

Importance

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

9 Methods

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