Passed
Push — master ( 03df52...d88a91 )
by Patrick
13:12
created

SqsFifoQueue   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 239
Duplicated Lines 0 %

Test Coverage

Coverage 95.38%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 50
c 2
b 1
f 0
dl 0
loc 239
ccs 62
cts 65
cp 0.9538
rs 10
wmc 22

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getMeta() 0 5 1
A getMetaPayload() 0 13 4
A getDeduplicationId() 0 19 4
A appendPayload() 0 13 3
A pushRaw() 0 13 2
A createPayload() 0 25 4
A createPayloadArray() 0 5 1
A setSqs() 0 5 1
A later() 0 3 1
1
<?php
2
3
namespace ShiftOneLabs\LaravelSqsFifoQueue;
4
5
use LogicException;
6
use Aws\Sqs\SqsClient;
7
use BadMethodCallException;
8
use InvalidArgumentException;
9
use Illuminate\Queue\SqsQueue;
10
use ShiftOneLabs\LaravelSqsFifoQueue\Support\Arr;
11
use ShiftOneLabs\LaravelSqsFifoQueue\Contracts\Queue\Deduplicator;
12
13
class SqsFifoQueue extends SqsQueue
14
{
15
    /**
16
     * The message group id of the fifo pipe in the queue.
17
     *
18
     * @var string
19
     */
20
    protected $group;
21
22
    /**
23
     * The driver to generate the deduplication id for the message.
24
     *
25
     * @var string
26
     */
27
    protected $deduplicator;
28
29
    /**
30
     * Create a new Amazon SQS queue instance.
31
     *
32
     * @param  \Aws\Sqs\SqsClient  $sqs
33
     * @param  string  $default
34
     * @param  string  $prefix
35
     * @param  string  $group
36
     * @param  string  $deduplicator
37
     *
38
     * @return void
39
     */
40 722
    public function __construct(SqsClient $sqs, $default, $prefix = '', $group = '', $deduplicator = '')
41
    {
42 722
        parent::__construct($sqs, $default, $prefix);
43
44 722
        $this->group = $group;
45 722
        $this->deduplicator = $deduplicator;
46 722
    }
47
48
    /**
49
     * Set the underlying SQS instance.
50
     *
51
     * @param  \Aws\Sqs\SqsClient  $sqs
52
     *
53
     * @return \ShiftOneLabs\LaravelSqsFifoQueue\SqsFifoQueue
54
     */
55 114
    public function setSqs(SqsClient $sqs)
56
    {
57 114
        $this->sqs = $sqs;
58
59 114
        return $this;
60
    }
61
62
    /**
63
     * Push a raw payload onto the queue.
64
     *
65
     * @param  string  $payload
66
     * @param  string|null  $queue
67
     * @param  array  $options
68
     *
69
     * @return mixed
70
     */
71 608
    public function pushRaw($payload, $queue = null, array $options = [])
72
    {
73
        $message = [
74 608
            'QueueUrl' => $this->getQueue($queue), 'MessageBody' => $payload, 'MessageGroupId' => $this->getMeta($payload, 'group', $this->group),
75 96
        ];
76
77 608
        if (($deduplication = $this->getDeduplicationId($payload, $queue)) !== false) {
78 380
            $message['MessageDeduplicationId'] = $deduplication;
79 60
        }
80
81 570
        $response = $this->sqs->sendMessage($message);
82
83 570
        return $response->get('MessageId');
84
    }
85
86
    /**
87
     * Push a new job onto the queue after a delay.
88
     *
89
     * @param  \DateTime|int  $delay
90
     * @param  string  $job
91
     * @param  mixed  $data
92
     * @param  string|null  $queue
93
     *
94
     * @return mixed
95
     *
96
     * @throws BadMethodCallException
97
     */
98 38
    public function later($delay, $job, $data = '', $queue = null)
99
    {
100 38
        throw new BadMethodCallException('FIFO queues do not support per-message delays.');
101
    }
102
103
    /**
104
     * Get the deduplication id for the given driver.
105
     *
106
     * @param  string  $payload
107
     * @param  string  $queue
108
     *
109
     * @return string|bool
110
     *
111
     * @throws InvalidArgumentException
112
     */
113 608
    protected function getDeduplicationId($payload, $queue)
114
    {
115 608
        $driver = $this->getMeta($payload, 'deduplicator', $this->deduplicator);
116
117 608
        if (empty($driver)) {
118 152
            return false;
119
        }
120
121 456
        if ($this->container->bound($key = 'queue.sqs-fifo.deduplicator.'.$driver)) {
122 418
            $deduplicator = $this->container->make($key);
123
124 418
            if ($deduplicator instanceof Deduplicator) {
125 418
                return $deduplicator->generate($payload, $queue);
126
            }
127
128
            throw new InvalidArgumentException(sprintf('Deduplication method [%s] must resolve to a %s implementation.', $driver, Deduplicator::class));
129
        }
130
131 38
        throw new InvalidArgumentException(sprintf('Unsupported deduplication method [%s].', $driver));
132
    }
133
134
    /**
135
     * Create a payload string from the given job and data.
136
     *
137
     * @param  mixed  $job
138
     * @param  mixed  $data
139
     * @param  string|null  $queue
140
     *
141
     * @return string
142
     *
143
     * @throws \LogicException
144
     * @throws \InvalidArgumentException
145
     * @throws \Illuminate\Queue\InvalidPayloadException
146
     */
147 342
    protected function createPayload($job, $data = '', $queue = null)
148
    {
149 342
        $payload = parent::createPayload($job, $data, $queue);
150
151 342
        if (!is_object($job)) {
152 190
            return $payload;
153
        }
154
155
        // Laravel 5.4 reworked payload generate. If the parent class has
156
        // the `createPayloadArray` method, it has already been called
157
        // through the parent call to the "createPayload" method.
158 152
        if (method_exists(get_parent_class($this), 'createPayloadArray')) {
159 8
            return $payload;
160
        }
161
162
        // Laravel <= 5.3 has the `setMeta` method. This is the method
163
        // used to add meta data to the payload generated by the
164
        // parent call to `createPayload` above.
165 144
        if (method_exists($this, 'setMeta')) {
166 144
            return $this->appendPayload($payload, $job);
167
        }
168
169
        // If neither of the above methods exist, we must be on a version
170
        // of Laravel that is not currently supported.
171
        throw new LogicException('"createPayloadArray" and "setMeta" methods both missing. This version of Laravel not supported.');
172
    }
173
174
    /**
175
     * Append meta data to the payload for Laravel <= 5.3.
176
     *
177
     * @param  string  $payload
178
     * @param  mixed  $job
179
     *
180
     * @return string
181
     */
182 144
    protected function appendPayload($payload, $job)
183
    {
184 144
        $meta = $this->getMetaPayload($job);
185
186 144
        if (array_key_exists('group', $meta)) {
187 36
            $payload = $this->setMeta($payload, 'group', $meta['group']);
0 ignored issues
show
Bug introduced by
The method setMeta() does not exist on ShiftOneLabs\LaravelSqsFifoQueue\SqsFifoQueue. ( Ignorable by Annotation )

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

187
            /** @scrutinizer ignore-call */ 
188
            $payload = $this->setMeta($payload, 'group', $meta['group']);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
188 6
        }
189
190 144
        if (array_key_exists('deduplicator', $meta)) {
191 72
            $payload = $this->setMeta($payload, 'deduplicator', $meta['deduplicator']);
192 12
        }
193
194 144
        return $payload;
195
    }
196
197
    /**
198
     * Create a payload array from the given job and data.
199
     *
200
     * @param  mixed  $job
201
     * @param  mixed  $data
202
     * @param  string|null  $queue
203
     *
204
     * @return array
205
     */
206 18
    protected function createPayloadArray($job, $data = '', $queue = null)
207
    {
208 18
        return array_merge(
209 18
            parent::createPayloadArray($job, $data, $queue),
210 18
            $this->getMetaPayload($job)
211
        );
212
    }
213
214
    /**
215
     * Get the meta data to add to the payload.
216
     *
217
     * @param  mixed  $job
218
     *
219
     * @return array
220
     */
221 162
    protected function getMetaPayload($job)
222
    {
223 162
        if (!is_object($job)) {
224 10
            return [];
225
        }
226
227 152
        return array_filter(
228
            [
229 152
                'group' => isset($job->messageGroupId) ? $job->messageGroupId : null,
230 152
                'deduplicator' => isset($job->deduplicator) ? $job->deduplicator : null,
231 24
            ],
232 152
            function ($value) {
233 152
                return $value !== null;
234 128
            }
235 24
        );
236
    }
237
238
    /**
239
     * Get additional meta from a payload string.
240
     *
241
     * @param  string  $payload
242
     * @param  string  $key
243
     * @param  mixed  $default
244
     *
245
     * @return mixed
246
     */
247 608
    protected function getMeta($payload, $key, $default = null)
248
    {
249 608
        $payload = json_decode($payload, true);
250
251 608
        return Arr::get($payload, $key, $default);
252
    }
253
}
254