Completed
Push — master ( 1f73f5...0e7a62 )
by Alexey
35:34
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]@gmail.com>
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
     * @return Manager
63
     */
64
    protected function connect()
65
    {
66
        $this->manager = new Manager();
67
68
        $this->manager->addConnector('mongo-thread', function () {
69
            return new MongoThreadConnector(Yii::$app->mongodb);
70
        });
71
72
        foreach ($this->connections as $name => $params) {
73
            $this->manager->addConnection($params, $name);
74
        }
75
76
        //Set as global to access
77
        $this->manager->setAsGlobal();
78
    }
79
80
    /**
81
     * Get queue manager instance
82
     *
83
     * @return mixed
84
     */
85
    public function getQueueManager()
86
    {
87
        return $this->manager->getQueueManager();
88
    }
89
90
    /**
91
     * Push new job to queue
92
     *
93
     * @param mixed $job
94
     * @param array $data
95
     * @param string $queue
96
     * @param string $connection
97
     *
98
     * @return mixed
99
     */
100
    public static function push($job, $data = [], $queue = 'default', $connection = 'default')
101
    {
102
        return Manager::push($job, $data, $queue, $connection);
103
    }
104
105
    /**
106
     * Push new job to queue if this job is not exist
107
     *
108
     * @param mixed $job
109
     * @param array $data
110
     * @param string $queue
111
     * @param string $connection
112
     *
113
     * @return mixed
114
     */
115
    public static function pushUnique($job, $data = [], $queue = 'default', $connection = 'default')
116
    {
117
        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...
118
            return Manager::push($job, $data, $queue, $connection);
119
        }
120
121
        return null;
122
    }
123
124
    /**
125
     * Push a new an array of jobs onto the queue.
126
     *
127
     * @param  array $jobs
128
     * @param  mixed $data
129
     * @param  string $queue
130
     * @param  string $connection
131
     *
132
     * @return mixed
133
     */
134
    public static function bulk($jobs, $data = '', $queue = null, $connection = null)
135
    {
136
        return Manager::bulk($jobs, $data, $queue, $connection);
137
    }
138
139
    /**
140
     * Push a new job onto the queue after a delay.
141
     *
142
     * @param  \DateTime|int $delay
143
     * @param  string $job
144
     * @param  mixed $data
145
     * @param  string $queue
146
     * @param  string $connection
147
     *
148
     * @return mixed
149
     */
150
    public static function later($delay, $job, $data = '', $queue = null, $connection = null)
151
    {
152
        return Manager::later($delay, $job, $data, $queue, $connection);
153
    }
154
155
    /**
156
     * Push a new job into the queue after a delay if job does not exist.
157
     *
158
     * @param  \DateTime|int $delay
159
     * @param  string $job
160
     * @param  mixed $data
161
     * @param  string $queue
162
     * @param  string $connection
163
     *
164
     * @return mixed
165
     */
166
    public static function laterUnique($delay, $job, $data = '', $queue = null, $connection = null)
167
    {
168
        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...
169
            return Manager::later($delay, $job, $data, $queue, $connection);
170
        }
171
172
        return null;
173
    }
174
}
175