EventSourcingModule::boot()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 18
ccs 11
cts 11
cp 1
crap 2
rs 9.9332
c 0
b 0
f 0
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\Store\EventStreamStore;
18
use ServiceBus\EventSourcing\EventStream\Store\SqlEventStreamStore;
19
use ServiceBus\EventSourcing\Indexes\Store\IndexStore;
20
use ServiceBus\EventSourcing\Indexes\Store\SqlIndexStore;
21
use ServiceBus\EventSourcing\Snapshots\Snapshotter;
22
use ServiceBus\EventSourcing\Snapshots\Store\SnapshotStore;
23
use ServiceBus\EventSourcing\Snapshots\Store\SqlSnapshotStore;
24
use ServiceBus\EventSourcing\Snapshots\Triggers\SnapshotTrigger;
25
use ServiceBus\EventSourcing\Snapshots\Triggers\SnapshotVersionTrigger;
26
use ServiceBus\Mutex\InMemoryMutexFactory;
27
use ServiceBus\Mutex\MutexFactory;
28
use Symfony\Component\DependencyInjection\ContainerBuilder;
29
use Symfony\Component\DependencyInjection\Definition;
30
use Symfony\Component\DependencyInjection\Reference;
31
32
/**
33
 * @todo: custom store initialization
34
 */
35
final class EventSourcingModule implements ServiceBusModule
36
{
37
    /**
38
     * @var string
39
     */
40
    private $eventStoreServiceId;
41
42
    /**
43
     * @var string
44
     */
45
    private $snapshotStoreServiceId;
46
47
    /**
48
     * @var string
49
     */
50
    private $indexerStore;
51
52
    /**
53
     * @var string|null
54
     */
55
    private $databaseAdapterServiceId;
56
57
    /**
58
     * @var string|null
59
     */
60
    private $customEventSerializerServiceId;
61
62
    /**
63
     * @var string|null
64
     */
65
    private $customSnapshotStrategyServiceId;
66
67
    /**
68
     * @param string $databaseAdapterServiceId
69
     *
70
     * @return self
71
     */
72 1
    public static function withSqlStorage(string $databaseAdapterServiceId): self
73
    {
74 1
        $self = new self(
75 1
            EventStreamStore::class,
76 1
            SnapshotStore::class,
77 1
            IndexStore::class
78
        );
79
80 1
        $self->databaseAdapterServiceId = $databaseAdapterServiceId;
81
82 1
        return $self;
83
    }
84
85
    /**
86
     * @param string $eventSerializerServiceId
87
     *
88
     * @return $this
89
     */
90
    public function withCustomEventSerializer(string $eventSerializerServiceId): self
91
    {
92
        $this->customEventSerializerServiceId = $eventSerializerServiceId;
93
94
        return $this;
95
    }
96
97
    /**
98
     * @param string $snapshotStrategyServiceId
99
     *
100
     * @return $this
101
     */
102
    public function withCustomSnapshotStrategy(string $snapshotStrategyServiceId): self
103
    {
104
        $this->customSnapshotStrategyServiceId = $snapshotStrategyServiceId;
105
106
        return $this;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112 1
    public function boot(ContainerBuilder $containerBuilder): void
113
    {
114
        /** Default configuration used */
115 1
        if (null !== $this->databaseAdapterServiceId)
116
        {
117 1
            $storeArguments = [new Reference($this->databaseAdapterServiceId)];
118
119 1
            $containerBuilder->addDefinitions([
120 1
                $this->eventStoreServiceId    => (new Definition(SqlEventStreamStore::class))->setArguments($storeArguments),
121 1
                $this->snapshotStoreServiceId => (new Definition(SqlSnapshotStore::class))->setArguments($storeArguments),
122 1
                $this->indexerStore           => (new Definition(SqlIndexStore::class))->setArguments($storeArguments),
123
            ]);
124
        }
125
126 1
        $this->registerMutexFactory($containerBuilder);
127 1
        $this->registerSnapshotter($containerBuilder);
128 1
        $this->registerEventSourcingProvider($containerBuilder);
129 1
        $this->registerIndexer($containerBuilder);
130 1
    }
131
132
    /**
133
     * @param ContainerBuilder $containerBuilder
134
     */
135 1
    private function registerMutexFactory(ContainerBuilder $containerBuilder): void
136
    {
137 1
        if (false === $containerBuilder->hasDefinition(MutexFactory::class))
138
        {
139 1
            $containerBuilder->addDefinitions([
140 1
                MutexFactory::class => new Definition(InMemoryMutexFactory::class),
141
            ]);
142
        }
143 1
    }
144
145
    /**
146
     * @param ContainerBuilder $containerBuilder
147
     *
148
     * @return void
149
     */
150 1
    private function registerIndexer(ContainerBuilder $containerBuilder): void
151
    {
152
        /** @psalm-suppress PossiblyNullArgument */
153 1
        $containerBuilder->addDefinitions([
154 1
            $this->indexerStore  => (new Definition(SqlIndexStore::class))->setArguments([new Reference($this->databaseAdapterServiceId)]),
0 ignored issues
show
Bug introduced by
It seems like $this->databaseAdapterServiceId can also be of type null; however, parameter $id of Symfony\Component\Depend...eference::__construct() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

154
            $this->indexerStore  => (new Definition(SqlIndexStore::class))->setArguments([new Reference(/** @scrutinizer ignore-type */ $this->databaseAdapterServiceId)]),
Loading history...
155 1
            IndexProvider::class => (new Definition(IndexProvider::class))->setArguments(
156
                [
157 1
                    new Reference($this->indexerStore),
158 1
                    new Reference(MutexFactory::class),
159
                ]
160
            ),
161
        ]);
162 1
    }
163
164
    /**
165
     * @param ContainerBuilder $containerBuilder
166
     *
167
     * @return void
168
     */
169 1
    private function registerEventSourcingProvider(ContainerBuilder $containerBuilder): void
170
    {
171
        $arguments = [
172 1
            new Reference($this->eventStoreServiceId),
173 1
            new Reference(Snapshotter::class),
174 1
            null !== $this->customEventSerializerServiceId
175
                ? new Reference($this->customEventSerializerServiceId)
176
                : null,
177 1
            new Reference('service_bus.logger'),
178
        ];
179
180 1
        $containerBuilder->addDefinitions([
181 1
            EventStreamRepository::class => (new Definition(EventStreamRepository::class))->setArguments($arguments),
182 1
            EventSourcingProvider::class => (new Definition(EventSourcingProvider::class))->setArguments(
183
                [
184 1
                    new Reference(EventStreamRepository::class),
185 1
                    new Reference(MutexFactory::class),
186
                ]
187
            ),
188
        ]);
189 1
    }
190
191
    /**
192
     * @param ContainerBuilder $containerBuilder
193
     *
194
     * @return void
195
     */
196 1
    private function registerSnapshotter(ContainerBuilder $containerBuilder): void
197
    {
198 1
        if (null === $this->customSnapshotStrategyServiceId)
199
        {
200 1
            $containerBuilder->addDefinitions([
201 1
                SnapshotTrigger::class => new Definition(SnapshotVersionTrigger::class),
202
            ]);
203
204 1
            $this->customSnapshotStrategyServiceId = SnapshotTrigger::class;
205
        }
206
207
        $arguments = [
208 1
            new Reference($this->snapshotStoreServiceId),
209 1
            new Reference($this->customSnapshotStrategyServiceId),
210 1
            new Reference('service_bus.logger'),
211
        ];
212
213 1
        $containerBuilder->addDefinitions([
214 1
            Snapshotter::class => (new Definition(Snapshotter::class))->setArguments($arguments),
215
        ]);
216 1
    }
217
218
    /**
219
     * @param string $eventStoreServiceId
220
     * @param string $snapshotStoreServiceId
221
     * @param string $indexerStore
222
     */
223 1
    private function __construct(string $eventStoreServiceId, string $snapshotStoreServiceId, string $indexerStore)
224
    {
225 1
        $this->eventStoreServiceId    = $eventStoreServiceId;
226 1
        $this->snapshotStoreServiceId = $snapshotStoreServiceId;
227 1
        $this->indexerStore           = $indexerStore;
228 1
    }
229
}
230