Completed
Push — master ( 1f73f5...0e7a62 )
by Alexey
35:34
created

JobQueue::bulk()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 4
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
Bug introduced by
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
Bug introduced by
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