Skip to content

Commit 409eb03

Browse files
authored
Merge pull request #12 from rapideinternet/upgrade/5.7
Update to 5.7 and more
2 parents 560873a + acdf6b9 commit 409eb03

File tree

8 files changed

+128
-50
lines changed

8 files changed

+128
-50
lines changed

.styleci.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ enabled:
6262
- print_to_echo
6363
- self_accessor
6464
- short_array_syntax
65-
- short_scalar_cast
6665
- single_blank_line_before_namespace
6766
- single_quote
6867
- space_after_semicolon
@@ -73,4 +72,4 @@ enabled:
7372
- unalign_double_arrow
7473
- unalign_equals
7574
- unary_operator_spaces
76-
- whitespace_after_comma_in_array
75+
- whitespace_after_comma_in_array

.travis.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ php:
66
- 5.6
77
- 7.0
88
- 7.1
9-
- hhvm
9+
- 7.2
10+
- 7.3
1011
- nightly
1112

1213
install:
1314
- ./travis-install.sh
1415
- travis_retry composer install --no-interaction
1516

1617
matrix:
17-
fast_finish: true
18-
allow_failures:
19-
- php: hhvm
20-
- php: nightly
18+
fast_finish: true
19+
allow_failures:
20+
- php: nightly
2121

2222
script:
23-
- phpunit --no-coverage
23+
- phpunit --no-coverage

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,45 @@ Kafka Queue driver for Laravel
2525
$ pecl install rdkafka
2626
```
2727

28-
3. Add the following to your php.ini file to enable the php-rdkafka extension
28+
3. a. Add the following to your php.ini file to enable the php-rdkafka extension
2929
`extension=rdkafka.so`
3030

31+
b. Check if rdkafka is installed
32+
__Note:__ If you want to run this on php-fpm restart your php-fpm first.
33+
34+
php -i | grep rdkafka
35+
36+
Your output should look something like this
37+
38+
rdkafka
39+
rdkafka support => enabled
40+
librdkafka version (runtime) => 1.0.0-RC2
41+
librdkafka version (build) => 0.11.4.0
42+
43+
3144
4. Install this package via composer using:
3245

33-
`composer require rapide/laravel-queue-kafka`
46+
composer require rapide/laravel-queue-kafka
3447

3548
5. Add LaravelQueueKafkaServiceProvider to `providers` array in `config/app.php`:
3649

37-
`Rapide\LaravelQueueKafka\LaravelQueueKafkaServiceProvider::class,`
50+
Rapide\LaravelQueueKafka\LaravelQueueKafkaServiceProvider::class,
3851

3952
If you are using Lumen, put this in `bootstrap/app.php`
4053

41-
`$app->register(Rapide\LaravelQueueKafka\LumenQueueKafkaServiceProvider::class);`
54+
$app->register(Rapide\LaravelQueueKafka\LumenQueueKafkaServiceProvider::class);
4255

4356
6. Add these properties to `.env` with proper values:
4457

4558
QUEUE_DRIVER=kafka
4659

60+
7. If you want to run a worker for a specific consumer group
61+
62+
export KAFKA_CONSUMER_GROUP_ID="group2" && php artisan queue:work --sleep=3 --tries=3
63+
64+
Explaination of consumergroups can be found in this article
65+
http://blog.cloudera.com/blog/2018/05/scalability-of-kafka-messaging-using-consumer-groups/
66+
4767
#### Usage
4868

4969
Once you completed the configuration you can use Laravel Queue API. If you used other queue drivers you do not need to change anything else. If you do not know how to use Queue API, please refer to the official Laravel documentation: http://laravel.com/docs/queues
@@ -67,4 +87,4 @@ You can contribute to this package by discovering bugs and opening issues. Pleas
6787

6888
#### Supported versions of Laravel
6989

70-
Tested on: [5.4]
90+
Tested on: [5.4, 5.5, 5.6, 5.7]

composer.json

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
"name": "rapide/laravel-queue-kafka",
33
"description": "Kafka driver for Laravel Queue",
44
"license": "MIT",
5+
"type": "library",
6+
"version": "1.0",
57
"authors": [
68
{
79
"name": "Peter Mein",
@@ -10,9 +12,10 @@
1012
],
1113
"require": {
1214
"php": ">=5.6.4",
13-
"illuminate/database": "5.4.*|5.5.*||5.6.*",
14-
"illuminate/support": "5.4.*|5.5.*|5.6.*",
15-
"illuminate/queue": "5.4.*|5.5.*|5.6.*"
15+
"illuminate/database": "5.4.*|5.5.*||5.6.*|5.7.*",
16+
"illuminate/support": "5.4.*|5.5.*|5.6.*|5.7.*",
17+
"illuminate/queue": "5.4.*|5.5.*|5.6.*|5.7.*",
18+
"ext-rdkafka": "*"
1619
},
1720
"require-dev": {
1821
"phpunit/phpunit": "^5.5",
@@ -23,6 +26,13 @@
2326
"Rapide\\LaravelQueueKafka\\": "src/"
2427
}
2528
},
29+
"extra": {
30+
"laravel": {
31+
"providers": [
32+
"Rapide\\LaravelQueueKafka\\LaravelQueueKafkaServiceProvider"
33+
]
34+
}
35+
},
2636
"minimum-stability": "dev",
2737
"prefer-stable": true
2838
}

config/kafka.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,8 @@
3232
*/
3333
'sleep_on_error' => env('KAFKA_ERROR_SLEEP', 5),
3434

35+
/*
36+
* Sleep when a deadlock is detected
37+
*/
38+
'sleep_on_deadlock' => env('KAFKA_DEADLOCK_SLEEP', 2),
3539
];
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Rapide\LaravelQueueKafka\Exceptions;
4+
5+
class QueueKafkaException extends \RuntimeException
6+
{
7+
//
8+
}

src/Queue/Jobs/KafkaJob.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,25 @@
99
use Illuminate\Queue\Jobs\Job;
1010
use Illuminate\Queue\Jobs\JobName;
1111
use Illuminate\Support\Str;
12+
use Rapide\LaravelQueueKafka\Exceptions\QueueKafkaException;
1213
use Rapide\LaravelQueueKafka\Queue\KafkaQueue;
1314
use RdKafka\Message;
1415

1516
class KafkaJob extends Job implements JobContract
1617
{
1718
use DetectsDeadlocks;
1819

20+
/**
21+
* @var KafkaQueue
22+
*/
1923
protected $connection;
24+
/**
25+
* @var KafkaQueue
26+
*/
2027
protected $queue;
28+
/**
29+
* @var Message
30+
*/
2131
protected $message;
2232

2333
/**
@@ -55,7 +65,7 @@ public function fire()
5565
$this->causedByDeadlock($exception) ||
5666
Str::contains($exception->getMessage(), ['detected deadlock'])
5767
) {
58-
sleep(2);
68+
sleep($this->connection->getConfig()['sleep_on_deadlock']);
5969
$this->fire();
6070

6171
return;
@@ -90,8 +100,12 @@ public function getRawBody()
90100
*/
91101
public function delete()
92102
{
93-
parent::delete();
94-
$this->connection->getConsumer()->commitAsync($this->message);
103+
try {
104+
parent::delete();
105+
$this->connection->getConsumer()->commitAsync($this->message);
106+
} catch (\RdKafka\Exception $exception) {
107+
throw new QueueKafkaException('Could not delete job from the queue', 0, $exception);
108+
}
95109
}
96110

97111
/**
@@ -134,7 +148,7 @@ public function release($delay = 0)
134148
*/
135149
public function getJobId()
136150
{
137-
return $this->message->get('correlation_id');
151+
return $this->message->key;
138152
}
139153

140154
/**
@@ -162,10 +176,10 @@ private function unserialize(array $body)
162176
return unserialize($body['data']['command']);
163177
} catch (Exception $exception) {
164178
if (
165-
$this->causedByDeadlock($exception) ||
166-
Str::contains($exception->getMessage(), ['detected deadlock'])
179+
$this->causedByDeadlock($exception)
180+
|| Str::contains($exception->getMessage(), ['detected deadlock'])
167181
) {
168-
sleep(2);
182+
sleep($this->connection->getConfig()['sleep_on_deadlock']);
169183

170184
return $this->unserialize($body);
171185
}

src/Queue/KafkaQueue.php

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Contracts\Queue\Queue as QueueContract;
88
use Illuminate\Queue\Queue;
99
use Log;
10+
use Rapide\LaravelQueueKafka\Exceptions\QueueKafkaException;
1011
use Rapide\LaravelQueueKafka\Queue\Jobs\KafkaJob;
1112

1213
class KafkaQueue extends Queue implements QueueContract
@@ -19,6 +20,10 @@ class KafkaQueue extends Queue implements QueueContract
1920
* @var int
2021
*/
2122
protected $sleepOnError;
23+
/**
24+
* @var array
25+
*/
26+
protected $config;
2227
/**
2328
* @var string
2429
*/
@@ -48,6 +53,7 @@ public function __construct(\RdKafka\Producer $producer, \RdKafka\KafkaConsumer
4853

4954
$this->producer = $producer;
5055
$this->consumer = $consumer;
56+
$this->config = $config;
5157
}
5258

5359
/**
@@ -84,18 +90,20 @@ public function push($job, $data = '', $queue = null)
8490
* @param string $queue
8591
* @param array $options
8692
*
93+
* @throws QueueKafkaException
94+
*
8795
* @return mixed
8896
*/
8997
public function pushRaw($payload, $queue = null, array $options = [])
9098
{
9199
try {
92100
$topic = $this->getTopic($queue);
93101

94-
$correlationId = $this->getCorrelationId();
102+
$pushRawCorrelationId = $this->getCorrelationId();
95103

96-
$topic->produce(RD_KAFKA_PARTITION_UA, 0, $payload, $correlationId);
104+
$topic->produce(RD_KAFKA_PARTITION_UA, 0, $payload, $pushRawCorrelationId);
97105

98-
return $correlationId;
106+
return $pushRawCorrelationId;
99107
} catch (ErrorException $exception) {
100108
$this->reportConnectionError('pushRaw', $exception);
101109
}
@@ -109,47 +117,54 @@ public function pushRaw($payload, $queue = null, array $options = [])
109117
* @param mixed $data
110118
* @param string $queue
111119
*
120+
* @throws QueueKafkaException
121+
*
112122
* @return mixed
113123
*/
114124
public function later($delay, $job, $data = '', $queue = null)
115125
{
116126
//Later is not sup
117-
throw new Exception('Later not yet implemented');
127+
throw new QueueKafkaException('Later not yet implemented');
118128
}
119129

120130
/**
121131
* Pop the next job off of the queue.
122132
*
123133
* @param string|null $queue
124134
*
135+
* @throws QueueKafkaException
136+
*
125137
* @return \Illuminate\Queue\Jobs\Job|null
126138
*/
127139
public function pop($queue = null)
128140
{
129-
$queue = $this->getQueueName($queue);
130-
if (!in_array($queue, $this->subscribedQueueNames)) {
131-
$this->subscribedQueueNames[] = $queue;
132-
$this->consumer->subscribe($this->subscribedQueueNames);
133-
}
141+
try {
142+
$queue = $this->getQueueName($queue);
143+
if (!in_array($queue, $this->subscribedQueueNames)) {
144+
$this->subscribedQueueNames[] = $queue;
145+
$this->consumer->subscribe($this->subscribedQueueNames);
146+
}
134147

135-
$message = $this->consumer->consume(1000);
148+
$message = $this->consumer->consume(1000);
136149

137-
if ($message === null) {
138-
return;
139-
}
150+
if ($message === null) {
151+
return null;
152+
}
140153

141-
switch ($message->err) {
142-
case RD_KAFKA_RESP_ERR_NO_ERROR:
143-
return new KafkaJob(
144-
$this->container, $this, $message,
145-
$this->connectionName, $queue ?: $this->defaultQueue
146-
);
147-
break;
148-
case RD_KAFKA_RESP_ERR__PARTITION_EOF:
149-
case RD_KAFKA_RESP_ERR__TIMED_OUT:
150-
break;
151-
default:
152-
throw new \Exception($message->errstr(), $message->err);
154+
switch ($message->err) {
155+
case RD_KAFKA_RESP_ERR_NO_ERROR:
156+
return new KafkaJob(
157+
$this->container, $this, $message,
158+
$this->connectionName, $queue ?: $this->defaultQueue
159+
);
160+
case RD_KAFKA_RESP_ERR__PARTITION_EOF:
161+
case RD_KAFKA_RESP_ERR__TIMED_OUT:
162+
break;
163+
default:
164+
throw new QueueKafkaException($message->errstr(), $message->err);
165+
}
166+
} catch (\RdKafka\Exception $exception) {
167+
throw new QueueKafkaException('Could not pop from the queue', 0, $exception);
153168
}
154169
}
155170

@@ -195,6 +210,14 @@ public function getCorrelationId()
195210
return $this->correlationId ?: uniqid('', true);
196211
}
197212

213+
/**
214+
* @return array
215+
*/
216+
public function getConfig()
217+
{
218+
return $this->config;
219+
}
220+
198221
/**
199222
* Create a payload array from the given job and data.
200223
*
@@ -216,15 +239,15 @@ protected function createPayloadArray($job, $data = '', $queue = null)
216239
* @param string $action
217240
* @param Exception $e
218241
*
219-
* @throws Exception
242+
* @throws QueueKafkaException
220243
*/
221244
protected function reportConnectionError($action, Exception $e)
222245
{
223246
Log::error('Kafka error while attempting ' . $action . ': ' . $e->getMessage());
224247

225248
// If it's set to false, throw an error rather than waiting
226249
if ($this->sleepOnError === false) {
227-
throw new \RuntimeException('Error writing data to the connection with Kafka');
250+
throw new QueueKafkaException('Error writing data to the connection with Kafka');
228251
}
229252

230253
// Sleep so that we don't flood the log file

0 commit comments

Comments
 (0)