Completed
Push — master ( 208887...1f73f5 )
by Alexey
38:56
created

JobQueue.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace yiicod\jobqueue;
4
5
use Illuminate\Queue\Capsule\Manager;
6
use Yii;
7
use yii\base\BootstrapInterface;
8
use yii\base\Component;
9
use yiicod\jobqueue\connectors\MongoThreadConnector;
10
11
/**
12
 * Yii component for laravel 5 queues to work with mongodb
13
 *
14
 * @author Orlov Alexey <[email protected]>
15
 * @author Virchenko Maksim <[email protected]>
16
 */
17
class JobQueue extends Component implements BootstrapInterface
18
{
19
    /**
20
     * Available connections
21
     *
22
     * @var array
23
     */
24
    public $connections = [
25
        'thread' => [
26
            'driver' => 'mongo-thread',
27
            'table' => 'yii_jobs_thread',
28
            'queue' => 'default',
29
            'expire' => 60,
30
            'limit' => 15, // Or 1
31
            'connectionName' => 'thread',
32
        ],
33
    ];
34
35
    /**
36
     * Encryption key
37
     *
38
     * @var string
39
     */
40
    public $privateKey = 'rc5lgpue80sr17nx';
41
42
    /**
43
     * Manager instance
44
     *
45
     * @var
46
     */
47
    private $manager = null;
48
49
    /**
50
     * Initialize
51
     *
52
     * @param \yii\base\Application $app
53
     */
54
    public function bootstrap($app)
55
    {
56
        $this->connect();
57
    }
58
59
    /**
60
     * Connect queue manager for mongo database
61
     *
62
     * @author Virchenko Maksim <[email protected]>
63
     *
64
     * @return Manager
65
     */
66
    protected function connect()
67
    {
68
        $this->manager = new Manager();
69
70
        $this->manager->addConnector('mongo-thread', function () {
71
            return new MongoThreadConnector(Yii::$app->mongodb);
72
        });
73
74
        foreach ($this->connections as $name => $params) {
75
            $this->manager->addConnection($params, $name);
76
        }
77
78
        //Set as global to access
79
        $this->manager->setAsGlobal();
80
    }
81
82
    /**
83
     * Get queue manager instance
84
     *
85
     * @return mixed
86
     */
87
    public function getQueueManager()
88
    {
89
        return $this->manager->getQueueManager();
90
    }
91
92
    /**
93
     * Push new job to queue
94
     *
95
     * @author Virchenko Maksim <[email protected]>
96
     *
97
     * @param mixed $job
98
     * @param array $data
99
     * @param string $queue
100
     * @param string $connection
101
     *
102
     * @return mixed
103
     */
104
    public static function push($job, $data = [], $queue = 'default', $connection = 'default')
105
    {
106
        return Manager::push($job, $data, $queue, $connection);
107
    }
108
109
    /**
110
     * Push new job to queue if this job is not exist
111
     *
112
     * @author Virchenko Maksim <[email protected]>
113
     *
114
     * @param mixed $job
115
     * @param array $data
116
     * @param string $queue
117
     * @param string $connection
118
     *
119
     * @return mixed
120
     */
121
    public static function pushUnique($job, $data = [], $queue = 'default', $connection = 'default')
122
    {
123
        if (false === Manager::connection($connection)->exists($job, $data, $queue)) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Illuminate\Contracts\Queue\Queue as the method exists() does only exist in the following implementations of said interface: yiicod\jobqueue\queues\MongoThreadQueue.

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
            return Manager::push($job, $data, $queue, $connection);
125
        }
126
127
        return null;
128
    }
129
130
    /**
131
     * Push a new an array of jobs onto the queue.
132
     *
133
     * @param  array $jobs
134
     * @param  mixed $data
135
     * @param  string $queue
136
     * @param  string $connection
137
     *
138
     * @return mixed
139
     */
140
    public static function bulk($jobs, $data = '', $queue = null, $connection = null)
141
    {
142
        return Manager::bulk($jobs, $data, $queue, $connection);
143
    }
144
145
    /**
146
     * Push a new job onto the queue after a delay.
147
     *
148
     * @param  \DateTime|int $delay
149
     * @param  string $job
150
     * @param  mixed $data
151
     * @param  string $queue
152
     * @param  string $connection
153
     *
154
     * @return mixed
155
     */
156
    public static function later($delay, $job, $data = '', $queue = null, $connection = null)
157
    {
158
        return Manager::later($delay, $job, $data, $queue, $connection);
159
    }
160
161
    /**
162
     * Push a new job into the queue after a delay if job does not exist.
163
     *
164
     * @param  \DateTime|int $delay
165
     * @param  string $job
166
     * @param  mixed $data
167
     * @param  string $queue
168
     * @param  string $connection
169
     *
170
     * @return mixed
171
     */
172
    public static function laterUnique($delay, $job, $data = '', $queue = null, $connection = null)
173
    {
174
        if (false === Manager::connection($connection)->exists($job, $data, $queue)) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Illuminate\Contracts\Queue\Queue as the method exists() does only exist in the following implementations of said interface: yiicod\jobqueue\queues\MongoThreadQueue.

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...
175
            return Manager::later($delay, $job, $data, $queue, $connection);
176
        }
177
178
        return null;
179
    }
180
}
181