Passed
Push — v4.2 ( 50993c...c387ce )
by Masiukevich
10:37
created

EventSourcingModule   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 66
c 1
b 0
f 0
dl 0
loc 165
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
    public static function withSqlStorage(string $databaseAdapterServiceId): self
60
    {
61
        $self = new self(
62
            EventStreamStore::class,
63
            SnapshotStore::class,
64
            IndexStore::class
65
        );
66
67
        $self->databaseAdapterServiceId = $databaseAdapterServiceId;
68
69
        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
    public function boot(ContainerBuilder $containerBuilder): void
90
    {
91
        /** Default configuration used */
92
        if (null !== $this->databaseAdapterServiceId)
93
        {
94
            $storeArguments = [new Reference($this->databaseAdapterServiceId)];
95
96
            $containerBuilder->addDefinitions([
97
                $this->eventStoreServiceId    => (new Definition(SqlEventStreamStore::class))->setArguments($storeArguments),
98
                $this->snapshotStoreServiceId => (new Definition(SqlSnapshotStore::class))->setArguments($storeArguments),
99
                $this->indexerStore           => (new Definition(SqlIndexStore::class))->setArguments($storeArguments),
100
            ]);
101
        }
102
103
        $this->registerMutexFactory($containerBuilder);
104
        $this->registerSnapshotter($containerBuilder);
105
        $this->registerEventSourcingProvider($containerBuilder);
106
        $this->registerIndexer($containerBuilder);
107
    }
108
109
    private function registerMutexFactory(ContainerBuilder $containerBuilder): void
110
    {
111
        if (false === $containerBuilder->hasDefinition(MutexFactory::class))
112
        {
113
            $containerBuilder->addDefinitions([
114
                MutexFactory::class => new Definition(InMemoryMutexFactory::class),
115
            ]);
116
        }
117
    }
118
119
    private function registerIndexer(ContainerBuilder $containerBuilder): void
120
    {
121
        /** @psalm-suppress PossiblyNullArgument */
122
        $containerBuilder->addDefinitions([
123
            $this->indexerStore  => (new Definition(SqlIndexStore::class))->setArguments([new Reference((string) $this->databaseAdapterServiceId)]),
124
            IndexProvider::class => (new Definition(IndexProvider::class))->setArguments(
125
                [
126
                    new Reference($this->indexerStore),
127
                    new Reference(MutexFactory::class),
128
                ]
129
            ),
130
        ]);
131
    }
132
133
    private function registerEventSourcingProvider(ContainerBuilder $containerBuilder): void
134
    {
135
        $serializer = null;
136
137
        if (null !== $this->customEventSerializerServiceId)
138
        {
139
            $serializer = new Reference($this->customEventSerializerServiceId);
140
        }
141
        else
142
        {
143
            $containerBuilder->addDefinitions(
144
                [
145
                    EventSerializer::class => (new Definition(DefaultEventSerializer::class))->setArguments([
146
                        new Reference('service_bus.decoder.default_handler'),
147
                    ]),
148
                ]
149
            );
150
151
            $serializer = new Reference(EventSerializer::class);
152
        }
153
154
        $arguments = [
155
            new Reference($this->eventStoreServiceId),
156
            new Reference(Snapshotter::class),
157
            $serializer,
158
            new Reference('service_bus.logger'),
159
        ];
160
161
        $containerBuilder->addDefinitions([
162
            EventStreamRepository::class => (new Definition(EventStreamRepository::class))->setArguments($arguments),
163
            EventSourcingProvider::class => (new Definition(EventSourcingProvider::class))->setArguments(
164
                [
165
                    new Reference(EventStreamRepository::class),
166
                    new Reference(MutexFactory::class),
167
                ]
168
            ),
169
        ]);
170
    }
171
172
    private function registerSnapshotter(ContainerBuilder $containerBuilder): void
173
    {
174
        if (null === $this->customSnapshotStrategyServiceId)
175
        {
176
            $containerBuilder->addDefinitions([
177
                SnapshotTrigger::class => new Definition(SnapshotVersionTrigger::class, [30]),
178
            ]);
179
180
            $this->customSnapshotStrategyServiceId = SnapshotTrigger::class;
181
        }
182
183
        $arguments = [
184
            new Reference($this->snapshotStoreServiceId),
185
            new Reference($this->customSnapshotStrategyServiceId),
186
            new Reference('service_bus.logger'),
187
        ];
188
189
        $containerBuilder->addDefinitions([
190
            Snapshotter::class => (new Definition(Snapshotter::class))->setArguments($arguments),
191
        ]);
192
    }
193
194
    /**
195
     * @param string $eventStoreServiceId
196
     * @param string $snapshotStoreServiceId
197
     * @param string $indexerStore
198
     */
199
    private function __construct(string $eventStoreServiceId, string $snapshotStoreServiceId, string $indexerStore)
200
    {
201
        $this->eventStoreServiceId    = $eventStoreServiceId;
202
        $this->snapshotStoreServiceId = $snapshotStoreServiceId;
203
        $this->indexerStore           = $indexerStore;
204
    }
205
}
206