PostponableJobStrategy   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 100%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 12
c 3
b 0
f 0
lcom 2
cbo 7
dl 0
loc 125
ccs 60
cts 60
cp 1
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A attach() 0 8 1
A getReleaseDelay() 0 4 1
A setReleaseDelay() 0 4 1
C onPostponeJobCheck() 0 72 8
1
<?php
2
3
namespace BsbPostponableJobStrategy\Strategy;
4
5
use BsbPostponableJobStrategy\Job\PostponableJobInterface;
6
use Doctrine\DBAL\Types\Type;
7
use SlmQueue\Strategy\AbstractStrategy;
8
use SlmQueue\Worker\WorkerEvent;
9
use SlmQueueDoctrine\Queue\DoctrineQueue;
10
use Zend\EventManager\EventManagerInterface;
11
use Zend\ServiceManager\ServiceLocatorInterface;
12
13
class PostponableJobStrategy extends AbstractStrategy
14
{
15
16
    /**
17
     * @var ServiceLocatorInterface
18
     */
19
    protected $serviceLocator;
20
21
    /**
22
     * @var int Time in seconds we use for the delay option while releasing a job back into the queue
23
     */
24
    protected $releaseDelay = 15;
25
26 16
    public function __construct(ServiceLocatorInterface $serviceLocator, array $options = null)
27
    {
28 16
        $this->serviceLocator = $serviceLocator;
29
30 16
        parent::__construct($options);
31 16
    }
32
33
    /**
34
     * {@inheritDoc}
35
     */
36 1
    public function attach(EventManagerInterface $events, $priority = 1)
37
    {
38 1
        $this->listeners[] = $events->attach(
39 1
            WorkerEvent::EVENT_PROCESS_JOB,
40 1
            [$this, 'onPostponeJobCheck'],
41
            PHP_INT_MAX
42 1
        );
43 1
    }
44
45
    /**
46
     * @return int
47
     */
48 3
    public function getReleaseDelay()
49
    {
50 3
        return $this->releaseDelay;
51
    }
52
53
    /**
54
     * @param int $releaseDelay
55
     */
56 2
    public function setReleaseDelay($releaseDelay)
57
    {
58 2
        $this->releaseDelay = $releaseDelay;
59 2
    }
60
61
    /**
62
     * @param WorkerEvent $event
63
     * @return void
64
     */
65 10
    public function onPostponeJobCheck(WorkerEvent $event)
66
    {
67 10
        $job = $event->getJob();
68
69 10
        if (!$job instanceof PostponableJobInterface) {
70 1
            return;
71
        }
72
73 9
        if (!$postponeUntil = $job->getMetadata('__postponeUntil')) {
74 3
            return;
75
        }
76
77
        /** @var DoctrineQueue $queue */
78 6
        $queue        = $event->getQueue();
79 6
        $queueOptions = $queue->getOptions();
80
        /** @var \Doctrine\DBAL\Connection $connection */
81 6
        $connection = $this->serviceLocator->get($queueOptions->getConnection());
82 6
        $queueOptions->getTableName();
0 ignored issues
show
Unused Code introduced by
The call to the method SlmQueueDoctrine\Options...Options::getTableName() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
83
84
        // remove id's that seem to have been processed
85 6
        $postponeUntil = array_filter($postponeUntil, function ($id) use ($connection, $queueOptions) {
86 6
            $sql = 'SELECT `status` FROM ' . $queueOptions->getTableName() . ' WHERE id = ?';
87 6
            $row = $connection->fetchAssoc($sql, [$id], [Type::SMALLINT]);
88
89
            // assume garbage collection has occured and job was processed successfully
90 6
            if (!$row) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $row of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
91 2
                return false;
92
            }
93
94 6
            return $row['status'] != DoctrineQueue::STATUS_DELETED;
95 6
        });
96
97
        // check for postponeUntil's that have been buried (failed by exception) fail this one too
98 6
        $ok = null;
0 ignored issues
show
Unused Code introduced by
$ok is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
99 6
        foreach ($postponeUntil as $key => $postponeUntilId) {
100 4
            $sql = 'SELECT `status` FROM ' . $queueOptions->getTableName() . ' WHERE id = ?';
101 4
            $row = $connection->fetchAssoc($sql, [$postponeUntilId], [Type::SMALLINT]);
102
103
            // assume garbage collection has occured and job was processed successfully
104 4
            if (!$row) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $row of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
105 3
                continue;
106
            }
107
108 1
            $ok = $row['status'] != DoctrineQueue::STATUS_BURIED;
109
110 1
            if ($ok === false) {
111 1
                $queue->bury(
112 1
                    $job,
113
                    [
114 1
                        'message' => sprintf(
115
                            'This postponed job has been buried because it depends on the execution ' .
116 1
                            'of a job (%s) that has been buried',
117
                            $postponeUntilId
118 1
                        )
119 1
                    ]
120 1
                );
121 1
                $event->stopPropagation();
122 1
                return;
123
            }
124 5
        }
125
126 5
        if ($postponeUntil) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $postponeUntil of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
127 3
            $postponeUntil = array_values($postponeUntil);
128
            // store still to be processed job's
129 3
            $job->setMetadata('__postponeUntil', $postponeUntil);
130 3
            $queue->release(
131 3
                $job,
132 3
                ['delay' => $job->getMetadata('__postponeReleaseDelay', $this->releaseDelay)]
133 3
            );
134 3
            $event->stopPropagation();
135 3
        }
136 5
    }
137
}
138