Completed
Push — v3.3 ( a2928b...399132 )
by Masiukevich
02:26
created

SqlSnapshotStore::load()   A

Complexity

Conditions 5
Paths 1

Size

Total Lines 53
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5.9256

Importance

Changes 6
Bugs 1 Features 0
Metric Value
cc 5
eloc 18
c 6
b 1
f 0
nc 1
nop 1
dl 0
loc 53
ccs 12
cts 18
cp 0.6667
crap 5.9256
rs 9.3554

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Store;
14
15
use function Amp\call;
16
use function ServiceBus\Common\datetimeToString;
17
use function ServiceBus\Storage\Sql\equalsCriteria;
18
use function ServiceBus\Storage\Sql\fetchOne;
19
use function ServiceBus\Storage\Sql\find;
20
use function ServiceBus\Storage\Sql\insertQuery;
21
use function ServiceBus\Storage\Sql\remove;
22
use Amp\Promise;
23
use ServiceBus\EventSourcing\AggregateId;
24
use ServiceBus\EventSourcing\Snapshots\Snapshot;
25
use ServiceBus\Storage\Common\BinaryDataDecoder;
26
use ServiceBus\Storage\Common\DatabaseAdapter;
27
28
/**
29
 *
30
 */
31
final class SqlSnapshotStore implements SnapshotStore
32
{
33
    private const TABLE_NAME = 'event_store_snapshots';
34
35
    /**
36
     * @var DatabaseAdapter
37
     */
38
    private $adapter;
39
40
    /**
41
     * @param DatabaseAdapter $adapter
42
     */
43 8
    public function __construct(DatabaseAdapter $adapter)
44
    {
45 8
        $this->adapter = $adapter;
46 8
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51 7
    public function save(Snapshot $snapshot): Promise
52
    {
53 7
        $adapter = $this->adapter;
54
55
        /** @psalm-suppress InvalidArgument Incorrect psalm unpack parameters (...$args) */
56 7
        return call(
57
            static function(Snapshot $snapshot) use ($adapter): \Generator
58
            {
59 7
                $insertQuery = insertQuery(self::TABLE_NAME, [
60 7
                    'id'                 => $snapshot->aggregate->id(),
61 7
                    'aggregate_id_class' => \get_class($snapshot->aggregate->id()),
62 7
                    'aggregate_class'    => \get_class($snapshot->aggregate),
63 7
                    'version'            => $snapshot->aggregate->version(),
64 7
                    'payload'            => \base64_encode(\serialize($snapshot)),
65 7
                    'created_at'         => datetimeToString($snapshot->aggregate->getCreatedAt()),
66
                ]);
67
68 7
                $compiledQuery = $insertQuery->compile();
69
70
                /** @psalm-suppress MixedTypeCoercion Invalid params() docblock */
71 7
                yield $adapter->execute($compiledQuery->sql(), $compiledQuery->params());
72 7
            },
73 7
            $snapshot
74
        );
75
    }
76
77
    /**
78
     * @psalm-suppress MixedTypeCoercion Incorrect resolving the value of the promise
79
     *
80
     * {@inheritdoc}
81
     */
82 7
    public function load(AggregateId $id): Promise
83
    {
84 7
        $adapter = $this->adapter;
85
86
        /** @psalm-suppress InvalidArgument Incorrect psalm unpack parameters (...$args) */
87 7
        return call(
88
            static function(AggregateId $id) use ($adapter): \Generator
89
            {
90 7
                $storedSnapshot = null;
91
92
                $criteria = [
93 7
                    equalsCriteria('id', $id->toString()),
94 7
                    equalsCriteria('aggregate_id_class', \get_class($id)),
95
                ];
96
97
                /** @var \ServiceBus\Storage\Common\ResultSet $resultSet */
98 7
                $resultSet = yield find($adapter, self::TABLE_NAME, $criteria);
99
100
                /**
101
                 * @psalm-var      array{
102
                 *   id: string,
103
                 *   aggregate_id_class: string,
104
                 *   aggregate_class: string,
105
                 *   version: int,
106
                 *   payload:string,
107
                 *   created_at: string
108
                 * }|null $data
109
                 *
110
                 * @var array<string, string>|null $data
111
                 */
112 7
                $data = yield fetchOne($resultSet);
113
114 7
                if (true === \is_array($data) && 0 !== \count($data))
115
                {
116
                    $payload = $data['payload'];
117
118
                    if ($adapter instanceof BinaryDataDecoder)
0 ignored issues
show
introduced by
$adapter is always a sub-type of ServiceBus\Storage\Common\BinaryDataDecoder.
Loading history...
119
                    {
120
                        $payload = $adapter->unescapeBinary($payload);
121
                    }
122
123
                    $snapshotContent = (string) \base64_decode($payload);
124
125
                    if ('' !== $snapshotContent)
126
                    {
127
                        /** @var Snapshot $storedSnapshot */
128
                        $storedSnapshot = \unserialize($snapshotContent, ['allowed_classes' => true]);
129
                    }
130
                }
131
132 7
                return $storedSnapshot;
133 7
            },
134 7
            $id
135
        );
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141 7
    public function remove(AggregateId $id): Promise
142
    {
143 7
        $adapter = $this->adapter;
144
145
        /** @psalm-suppress InvalidArgument Incorrect psalm unpack parameters (...$args) */
146 7
        return call(
147
            static function(AggregateId $id) use ($adapter): \Generator
148
            {
149
                $criteria = [
150 7
                    equalsCriteria('id', $id->toString()),
151 7
                    equalsCriteria('aggregate_id_class', \get_class($id)),
152
                ];
153
154 7
                yield remove($adapter, self::TABLE_NAME, $criteria);
155 7
            },
156 7
            $id
157
        );
158
    }
159
}
160