Completed
Pull Request — master (#13)
by Antonio
07:54
created

SqsQueueStoreAdapter::ack()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 12.9353

Importance

Changes 5
Bugs 0 Features 1
Metric Value
c 5
b 0
f 1
dl 0
loc 25
ccs 3
cts 17
cp 0.1765
rs 8.5806
cc 4
eloc 15
nc 4
nop 1
crap 12.9353
1
<?php
2
namespace Da\Mailer\Queue\Backend\Sqs;
3
4
use Da\Mailer\Exception\InvalidCallException;
5
use Da\Mailer\Queue\Backend\MailJobInterface;
6
use Da\Mailer\Queue\Backend\QueueStoreAdapterInterface;
7
8
class SqsQueueStoreAdapter implements QueueStoreAdapterInterface
9
{
10
    /**
11
     * @var string the name of the queue to store the messages
12
     */
13
    private $queueName;
14
    /**
15
     * @var string the URL of the queue to store the messages
16
     */
17
    private $queueUrl;
18
    /**
19
     * @var SqsQueueStoreConnection
20
     */
21
    protected $connection;
22
23
    /**
24
     * PdoQueueStoreAdapter constructor.
25
     *
26
     * @param SqsQueueStoreConnection $connection
27
     * @param string $queueName the name of the queue in the SQS where the mail jobs are stored
28
     */
29 5
    public function __construct(SqsQueueStoreConnection $connection, $queueName = 'mail_queue')
30
    {
31 5
        $this->connection = $connection;
32 5
        $this->queueName = $queueName;
33 5
        $this->init();
34 5
    }
35
36
    /**
37
     * @return SqsQueueStoreAdapter
38
     */
39 5
    public function init()
40
    {
41 5
        $this->getConnection()->connect();
42
43
        // create new queue or get existing one
44 5
        $queue = $this->getConnection()->getInstance()->createQueue([
45 5
            'QueueName' => $this->queueName,
46 5
        ]);
47 5
        $this->queueUrl = $queue->get('QueueUrl');
48
49 5
        return $this;
50
    }
51
52
    /**
53
     * @return SqsQueueStoreConnection
54
     */
55 5
    public function getConnection()
56
    {
57 5
        return $this->connection;
58
    }
59
60
    /**
61
     * @param MailJobInterface|SqsMailJob $mailJob
62
     *
63
     * @return bool whether it has been successfully queued or not
64
     */
65 3
    public function enqueue(MailJobInterface $mailJob)
66
    {
67 3
        $result = $this->getConnection()->getInstance()->sendMessage([
68 3
            'QueueUrl' => $this->queueUrl,
69 3
            'MessageBody' => $mailJob->getMessage(),
70 3
            'DelaySeconds' => $mailJob->getDelaySeconds(),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Da\Mailer\Queue\Backend\MailJobInterface as the method getDelaySeconds() does only exist in the following implementations of said interface: Da\Mailer\Queue\Backend\Sqs\SqsMailJob.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
71 3
            'Attempt' => $mailJob->getAttempt(),
72 3
        ]);
73
        $messageId = $result->get('MessageId');
74
75
        return $messageId !== null && is_string($messageId);
76
    }
77
78
    /**
79
     * Returns a MailJob fetched from Amazon SQS.
80
     *
81
     * @return MailJobInterface|SqsMailJob
82
     */
83
    public function dequeue()
84
    {
85
        $result = $this->getConnection()->getInstance()->receiveMessage([
86
            'QueueUrl' => $this->queueUrl,
87
        ]);
88
89
        if (($result = $result->getPath('Messages/*')) === null) {
90
            return null;
91
        }
92
93
        return new SqsMailJob([
94
            'id' => $result['MessageId'],
95
            'receiptHandle' => $result['ReceiptHandle'],
96
            'message' => $result['Body'],
97
            'attempt' => $result['Attempt'],
98
        ]);
99
    }
100
101
    /**
102
     * @param MailJobInterface|SqsMailJob $mailJob
103
     *
104
     * @return bool
105
     */
106 1
    public function ack(MailJobInterface $mailJob)
107
    {
108 1
        if ($mailJob->isNewRecord()) {
109 1
            throw new InvalidCallException('SqsMailJob cannot be a new object to be acknowledged');
110
        }
111
112
        if ($mailJob->getDeleted()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Da\Mailer\Queue\Backend\MailJobInterface as the method getDeleted() does only exist in the following implementations of said interface: Da\Mailer\Queue\Backend\Sqs\SqsMailJob.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
113
            $this->getConnection()->getInstance()->deleteMessage([
114
                'QueueUrl' => $this->queueUrl,
115
                'ReceiptHandle' => $mailJob->getReceiptHandle(),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Da\Mailer\Queue\Backend\MailJobInterface as the method getReceiptHandle() does only exist in the following implementations of said interface: Da\Mailer\Queue\Backend\Sqs\SqsMailJob.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
116
            ]);
117
118
            return true;
119
        } elseif ($mailJob->getVisibilityTimeout() !== null) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Da\Mailer\Queue\Backend\MailJobInterface as the method getVisibilityTimeout() does only exist in the following implementations of said interface: Da\Mailer\Queue\Backend\Sqs\SqsMailJob.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
120
            $this->getConnection()->getInstance()->changeMessageVisibility([
121
                'QueueUrl' => $this->queueUrl,
122
                'ReceiptHandle' => $mailJob->getReceiptHandle(),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Da\Mailer\Queue\Backend\MailJobInterface as the method getReceiptHandle() does only exist in the following implementations of said interface: Da\Mailer\Queue\Backend\Sqs\SqsMailJob.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
123
                'VisibilityTimeout' => $mailJob->getVisibilityTimeout(),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Da\Mailer\Queue\Backend\MailJobInterface as the method getVisibilityTimeout() does only exist in the following implementations of said interface: Da\Mailer\Queue\Backend\Sqs\SqsMailJob.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
124
            ]);
125
126
            return true;
127
        }
128
129
        return false;
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135
    public function isEmpty()
136
    {
137
        $attributes = $this->getConnection()->getInstance()->getQueueAttributes([
138
            'QueueUrl' => $this->queueUrl,
139
            'AttributeNames' => ['ApproximateNumberOfMessages'],
140
        ]);
141
142
        return $attributes->getPath('Attributes/ApproximateNumberOfMessages') == 0;
143
    }
144
}
145