Skip to content

Commit b605615

Browse files
authored
v 1.9.1
1 parent c322596 commit b605615

File tree

7 files changed

+156
-21
lines changed

7 files changed

+156
-21
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## CHANGELOG
22

3+
### v1.9.1 (2019-10-12)
4+
- Fixed bug: parser result error for transactions/pipelines https://github.com/cheprasov/php-redis-client/issues/72
5+
36
### v1.9.0 (2019-07-16)
47
- Support Redis 5
58
- Added stream commands: XACK, XADD, XCLAIM, XDEL, XGROUP, XINFO, XLEN, XPENDING, XRANGE, XREAD, XREADGROUP, XREVRANGE, XTRIM.

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[![MIT license](http://img.shields.io/badge/license-MIT-brightgreen.svg)](http://opensource.org/licenses/MIT)
22
[![Latest Stable Version](https://poser.pugx.org/cheprasov/php-redis-client/v/stable)](https://packagist.org/packages/cheprasov/php-redis-client)
33
[![Total Downloads](https://poser.pugx.org/cheprasov/php-redis-client/downloads)](https://packagist.org/packages/cheprasov/php-redis-client)
4-
# RedisClient v1.9.0 for PHP >= 5.5
4+
# RedisClient v1.9.1 for PHP >= 5.5
55

66
## About
77
RedisClient is a fast, fully-functional and user-friendly client for Redis, optimized for performance. RedisClient supports the latest versions of Redis starting from __2.6__ to __5.0__

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cheprasov/php-redis-client",
3-
"version": "1.9.0",
3+
"version": "1.9.1",
44
"description": "Php client for Redis. It is a fast, fully-functional and user-friendly client for Redis, optimized for performance. RedisClient supports the latest versions of Redis starting from 2.6 to 5.0",
55
"homepage": "http://github.com/cheprasov/php-redis-client",
66
"minimum-stability": "stable",

src/RedisClient/Client/AbstractRedisClient.php

+43-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
abstract class AbstractRedisClient {
2828

29-
const VERSION = '1.9.0';
29+
const VERSION = '1.9.1';
3030

3131
const CONFIG_SERVER = 'server';
3232
const CONFIG_TIMEOUT = 'timeout';
@@ -36,6 +36,12 @@ abstract class AbstractRedisClient {
3636
const CONFIG_VERSION = 'version';
3737
const CONFIG_CONNECTION = 'connection';
3838

39+
const TRANSACTION_RESPONSE_QUEUED = 'QUEUED';
40+
41+
const TRANSACTION_MODE_NONE = 0;
42+
const TRANSACTION_MODE_STARTED = 1;
43+
const TRANSACTION_MODE_EXECUTED = 2;
44+
3945
/**
4046
* Default configuration
4147
* @var array
@@ -69,6 +75,17 @@ abstract class AbstractRedisClient {
6975
*/
7076
protected $ClusterMap;
7177

78+
79+
/**
80+
* @var int
81+
*/
82+
protected $transactionMode = self::TRANSACTION_MODE_NONE;
83+
84+
/**
85+
* @var array[]|null
86+
*/
87+
protected $responseParsers = null;
88+
7289
/**
7390
* @param array|null $config
7491
*/
@@ -159,9 +176,25 @@ protected function executeCommand(array $command, $keys, array $params = null, $
159176
if ($response instanceof ErrorResponseException) {
160177
throw $response;
161178
}
162-
if (isset($parserId)) {
163-
return ResponseParser::parse($parserId, $response);
179+
180+
if ($this->transactionMode === self::TRANSACTION_MODE_NONE) {
181+
if (isset($parserId)) {
182+
return ResponseParser::parse($parserId, $response);
183+
}
184+
} else {
185+
if ($this->transactionMode === self::TRANSACTION_MODE_STARTED) {
186+
if ($response === self::TRANSACTION_RESPONSE_QUEUED) {
187+
$this->responseParsers[] = $parserId;
188+
}
189+
} elseif ($this->transactionMode === self::TRANSACTION_MODE_EXECUTED) {
190+
$this->setTransactionMode(self::TRANSACTION_MODE_NONE);
191+
if (is_array($response) && count($this->responseParsers)
192+
&& count($this->responseParsers) === count($response)) {
193+
return array_map([ResponseParser::class, 'parse'], $this->responseParsers, $response);
194+
}
195+
}
164196
}
197+
165198
return $response;
166199
}
167200

@@ -265,6 +298,13 @@ protected function getStructure(array $command, array $params = null) {
265298
return $command;
266299
}
267300

301+
/**
302+
* @param int $transactionMode
303+
*/
304+
protected function setTransactionMode($transactionMode) {
305+
$this->transactionMode = $transactionMode;
306+
}
307+
268308
/**
269309
* @param null|Pipeline|\Closure $Pipeline
270310
* @return mixed|Pipeline

src/RedisClient/Command/Traits/Version2x6/TransactionsCommandsTrait.php

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
*/
1111
namespace RedisClient\Command\Traits\Version2x6;
1212

13+
use RedisClient\Client\AbstractRedisClient;
14+
1315
/**
1416
* Transactions Commands
1517
* @link http://redis.io/commands#transactions
@@ -36,6 +38,7 @@ public function discard() {
3638
* @return mixed
3739
*/
3840
public function exec() {
41+
$this->setTransactionMode(AbstractRedisClient::TRANSACTION_MODE_EXECUTED);
3942
return $this->returnCommand(['EXEC']);
4043
}
4144

@@ -47,6 +50,7 @@ public function exec() {
4750
* @return bool Always True
4851
*/
4952
public function multi() {
53+
$this->setTransactionMode(AbstractRedisClient::TRANSACTION_MODE_STARTED);
5054
return $this->returnCommand(['MULTI']);
5155
}
5256

src/RedisClient/Pipeline/AbstractPipeline.php

+35-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111
namespace RedisClient\Pipeline;
1212

13+
use RedisClient\Client\AbstractRedisClient;
1314
use RedisClient\Command\Response\ResponseParser;
1415
use RedisClient\Exception\CommandNotFoundException;
1516
use RedisClient\Exception\ErrorException;
@@ -26,6 +27,11 @@ abstract class AbstractPipeline implements PipelineInterface {
2627
*/
2728
protected $keys = [];
2829

30+
/**
31+
* @var int
32+
*/
33+
protected $transactionMode = AbstractRedisClient::TRANSACTION_MODE_NONE;
34+
2935
/**
3036
* @param \Closure|null $Closure
3137
*/
@@ -74,6 +80,13 @@ protected function subscribeCommand(array $subCommand, array $unsubCommand, arra
7480
throw new ErrorException('Do not use subscribe in pipeline');
7581
}
7682

83+
/**
84+
* @param int $transactionMode
85+
*/
86+
protected function setTransactionMode($transactionMode) {
87+
$this->transactionMode = $transactionMode;
88+
}
89+
7790
/**
7891
* @return array[]
7992
*/
@@ -102,13 +115,30 @@ public function getStructure() {
102115
* @return mixed
103116
*/
104117
public function parseResponse($responses) {
105-
foreach ($responses as $n => $response) {
106-
if (empty($this->commandLines[$n][2])) {
107-
// todo: check
108-
continue;
118+
if ($this->transactionMode === AbstractRedisClient::TRANSACTION_MODE_NONE) {
119+
foreach ($responses as $n => $response) {
120+
if (empty($this->commandLines[$n][2])) {
121+
// todo: check
122+
continue;
123+
}
124+
$responses[$n] = ResponseParser::parse($this->commandLines[$n][2], $response);
125+
}
126+
return $responses;
127+
}
128+
129+
if ($this->transactionMode === AbstractRedisClient::TRANSACTION_MODE_EXECUTED) {
130+
$this->transactionMode = AbstractRedisClient::TRANSACTION_MODE_NONE;
131+
$execResponses = array_pop($responses);
132+
foreach ($execResponses as $n => $response) {
133+
// MULTI command is ignored
134+
if (empty($this->commandLines[$n + 1][2])) {
135+
continue;
136+
}
137+
$execResponses[$n] = ResponseParser::parse($this->commandLines[$n + 1][2], $response);
109138
}
110-
$responses[$n] = ResponseParser::parse($this->commandLines[$n][2], $response);
139+
$responses[] = $execResponses;
111140
}
141+
112142
return $responses;
113143
}
114144

tests/Integration/Version2x6/PipelineTest.php

+69-11
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,19 @@ public function test_separate() {
3636
$this->assertSame($Pipeline, $Pipeline->incr('bar'));
3737
$this->assertSame($Pipeline, $Pipeline->get('bar'));
3838
$this->assertSame($Pipeline, $Pipeline->mget(['foo', 'bar']));
39-
$this->assertSame([true, 5, '5', true, 3, '3', ['5', '3']], $Redis->pipeline($Pipeline));
39+
$this->assertSame($Pipeline, $Pipeline->time());
40+
41+
$result = $Redis->pipeline($Pipeline);
42+
43+
$this->assertSame(8, count($result));
44+
$this->assertSame(true, $result[0]);
45+
$this->assertSame(5, $result[1]);
46+
$this->assertSame('5', $result[2]);
47+
$this->assertSame(true, $result[3]);
48+
$this->assertSame(3, $result[4]);
49+
$this->assertSame('3', $result[5]);
50+
$this->assertSame(['5', '3'], $result[6]);
51+
$this->assertSame(true, is_numeric($result[7]));
4052

4153
/** @var Pipeline $Pipeline */
4254
$Pipeline = $Redis->pipeline();
@@ -61,15 +73,28 @@ public function test_pipeline() {
6173
$Pipeline = $Redis->pipeline();
6274
$this->assertInstanceOf(PipelineInterface::class, $Pipeline);
6375

64-
$this->assertSame(
65-
[true, 5, '5', true, 3, '3', ['5', '3']],
66-
$Redis->pipeline(
67-
$Pipeline->set('foo', '4')->incr('foo')->get('foo')
68-
->set('bar', '2')->incr('bar')->get('bar')
69-
->mget(['foo', 'bar'])
70-
)
76+
$result = $Redis->pipeline(
77+
$Pipeline
78+
->set('foo', '4')
79+
->incr('foo')
80+
->get('foo')
81+
->set('bar', '2')
82+
->incr('bar')
83+
->get('bar')
84+
->mget(['foo', 'bar'])
85+
->time()
7186
);
7287

88+
$this->assertSame(8, count($result));
89+
$this->assertSame(true, $result[0]);
90+
$this->assertSame(5, $result[1]);
91+
$this->assertSame('5', $result[2]);
92+
$this->assertSame(true, $result[3]);
93+
$this->assertSame(3, $result[4]);
94+
$this->assertSame('3', $result[5]);
95+
$this->assertSame(['5', '3'], $result[6]);
96+
$this->assertSame(true, is_numeric($result[7]));
97+
7398
/** @var Pipeline $Pipeline */
7499
$Pipeline = $Redis->pipeline();
75100
$this->assertInstanceOf(PipelineInterface::class, $Pipeline);
@@ -127,10 +152,11 @@ public function test_transaction() {
127152
->set('bar', 'new')
128153
->get('bar')
129154
->echo('hello word')
155+
->time()
130156
->exec();
131157
});
132158

133-
$this->assertSame(10, count($result));
159+
$this->assertSame(11, count($result));
134160
$this->assertSame(true, $result[0]);
135161
$this->assertSame('QUEUED', $result[1]);
136162
$this->assertSame('QUEUED', $result[2]);
@@ -140,10 +166,40 @@ public function test_transaction() {
140166
$this->assertSame('QUEUED', $result[6]);
141167
$this->assertSame('QUEUED', $result[7]);
142168
$this->assertSame('QUEUED', $result[8]);
169+
$this->assertSame('QUEUED', $result[9]);
143170

144-
$result = $result[9];
171+
$result = $result[10];
145172

146-
$this->assertSame(8, count($result));
173+
$this->assertSame(9, count($result));
174+
$this->assertSame(true, $result[0]);
175+
$this->assertSame(true, $result[1]);
176+
$this->assertSame('bar', $result[2]);
177+
$this->assertInstanceOf(ErrorResponseException::class, $result[3]);
178+
$this->assertInstanceOf(ErrorResponseException::class, $result[4]);
179+
$this->assertSame(true, $result[5]);
180+
$this->assertSame('new', $result[6]);
181+
$this->assertSame('hello word', $result[7]);
182+
$this->assertSame(true, is_string($result[8]));
183+
$this->assertSame(true, is_numeric($result[8][0]));
184+
}
185+
186+
public function test_transactionWithoutPipeline() {
187+
$Redis = static::$Redis;
188+
189+
/** @var Pipeline $Pipeline */
190+
$this->assertSame(true, $Redis->multi());
191+
$this->assertSame('QUEUED', $Redis->set('foo', 'foo'));
192+
$this->assertSame('QUEUED', $Redis->set('bar', 'bar'));
193+
$this->assertSame('QUEUED', $Redis->get('bar'));
194+
$this->assertSame('QUEUED', $Redis->hincrby('foo', 'foo', 1));
195+
$this->assertSame('QUEUED', $Redis->lpush('bar', 'bar'));
196+
$this->assertSame('QUEUED', $Redis->set('bar', 'new'));
197+
$this->assertSame('QUEUED', $Redis->get('bar'));
198+
$this->assertSame('QUEUED', $Redis->echo('hello word'));
199+
$this->assertSame('QUEUED', $Redis->time());
200+
$result = $Redis->exec();
201+
202+
$this->assertSame(9, count($result));
147203
$this->assertSame(true, $result[0]);
148204
$this->assertSame(true, $result[1]);
149205
$this->assertSame('bar', $result[2]);
@@ -152,6 +208,8 @@ public function test_transaction() {
152208
$this->assertSame(true, $result[5]);
153209
$this->assertSame('new', $result[6]);
154210
$this->assertSame('hello word', $result[7]);
211+
$this->assertSame(true, is_string($result[8]));
212+
$this->assertSame(true, is_numeric($result[8][0]));
155213
}
156214

157215
}

0 commit comments

Comments
 (0)