Passed
Push — v3.3 ( 1e1106...84677f )
by Masiukevich
03:38 queued 10s
created

Snapshotter   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Test Coverage

Coverage 65.85%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 41
c 2
b 0
f 0
dl 0
loc 137
ccs 27
cts 41
cp 0.6585
rs 10
wmc 6

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A load() 0 32 2
A store() 0 34 2
A snapshotMustBeCreated() 0 3 1
1
<?php
2
3
/**
4
 * Event Sourcing implementation.
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\Snapshots;
14
15
use function Amp\call;
16
use Amp\Promise;
17
use Psr\Log\LoggerInterface;
18
use Psr\Log\NullLogger;
19
use ServiceBus\EventSourcing\Aggregate;
20
use ServiceBus\EventSourcing\AggregateId;
21
use ServiceBus\EventSourcing\Snapshots\Store\SnapshotStore;
22
use ServiceBus\EventSourcing\Snapshots\Triggers\SnapshotTrigger;
23
24
/**
25
 *
26
 */
27
final class Snapshotter
28
{
29
    /**
30
     * Snapshot storage.
31
     *
32
     * @var SnapshotStore
33
     */
34
    private $store;
35
36
    /**
37
     * Snapshot generation trigger.
38
     *
39
     * @var SnapshotTrigger
40
     */
41
    private $trigger;
42
43
    /**
44
     * Logger.
45
     *
46
     * @var LoggerInterface
47
     */
48
    private $logger;
49
50
    /**
51
     * @param SnapshotStore        $store
52
     * @param SnapshotTrigger      $trigger
53
     * @param LoggerInterface|null $logger
54
     */
55 8
    public function __construct(
56
        SnapshotStore $store,
57
        SnapshotTrigger $trigger,
58
        LoggerInterface $logger = null
59
    ) {
60 8
        $this->store   = $store;
61 8
        $this->trigger = $trigger;
62 8
        $this->logger  = $logger ?? new NullLogger();
63 8
    }
64
65
    /**
66
     * Load snapshot for aggregate.
67
     *
68
     * @psalm-suppress MixedTypeCoercion Incorrect resolving the value of the promise
69
     *
70
     * @param AggregateId $id
71
     *
72
     * @return Promise<\ServiceBus\EventSourcing\Snapshots\Snapshot|null>
73
     */
74 7
    public function load(AggregateId $id): Promise
75
    {
76 7
        $store  = $this->store;
77 7
        $logger = $this->logger;
78
79
        /** @psalm-suppress InvalidArgument Incorrect psalm unpack parameters (...$args) */
80 7
        return call(
81
            static function(AggregateId $id) use ($store, $logger): \Generator
82
            {
83 7
                $snapshot = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $snapshot is dead and can be removed.
Loading history...
84
85
                try
86
                {
87
                    /** @var Snapshot|null $snapshot */
88 7
                    $snapshot = yield $store->load($id);
89
                }
90
                catch (\Throwable $throwable)
91
                {
92
                    $logger->error(
93
                        'Error loading snapshot of aggregate with identifier "{aggregateIdClass}:{aggregateId}"',
94
                        [
95
                            'aggregateIdClass' => \get_class($id),
96
                            'aggregateId'      => $id->toString(),
97
                            'throwableMessage' => $throwable->getMessage(),
98
                            'throwablePoint'   => \sprintf('%s:%d', $throwable->getFile(), $throwable->getLine()),
99
                        ]
100
                    );
101
                }
102
103 7
                return $snapshot;
104 7
            },
105 7
            $id
106
        );
107
    }
108
109
    /**
110
     * Store new snapshot.
111
     *
112
     * @param Snapshot $snapshot
113
     *
114
     * @return Promise It doesn't return any result
115
     */
116 7
    public function store(Snapshot $snapshot): Promise
117
    {
118 7
        $store  = $this->store;
119 7
        $logger = $this->logger;
120
121
        /** @psalm-suppress InvalidArgument Incorrect psalm unpack parameters (...$args) */
122 7
        return call(
123
            static function(Snapshot $snapshot) use ($store, $logger): \Generator
124
            {
125 7
                $id = $snapshot->aggregate->id();
126
127
                try
128
                {
129 7
                    yield $store->remove($id);
130 7
                    yield $store->save($snapshot);
131
                }
132
                catch (\Throwable $throwable)
133
                {
134
                    $logger->error(
135
                        'Error saving snapshot of aggregate with identifier "{aggregateIdClass}:{aggregateId}"',
136
                        [
137
                            'aggregateIdClass' => \get_class($id),
138
                            'aggregateId'      => $id->toString(),
139
                            'throwableMessage' => $throwable->getMessage(),
140
                            'throwablePoint'   => \sprintf('%s:%d', $throwable->getFile(), $throwable->getLine()),
141
                        ]
142
                    );
143
                }
144
                finally
145 7
                {
146 7
                    unset($id);
147
                }
148 7
            },
149 7
            $snapshot
150
        );
151
    }
152
153
    /**
154
     * A snapshot must be created.
155
     *
156
     * @param Aggregate $aggregate
157
     * @param Snapshot  $previousSnapshot
158
     *
159
     * @return bool
160
     */
161 7
    public function snapshotMustBeCreated(Aggregate $aggregate, Snapshot $previousSnapshot = null): bool
162
    {
163 7
        return $this->trigger->snapshotMustBeCreated($aggregate, $previousSnapshot);
164
    }
165
}
166