• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

predis / predis / 13716769884

07 Mar 2025 08:31AM UTC coverage: 92.8% (+0.03%) from 92.772%
13716769884

push

github

web-flow
Added support for transactions in OSS Cluster (#1497)

* Added support for transactions in OSS Cluster

* Updated test cases

* Updated version restriction

* Updated server version restriction

* Added test skip for Relay

* Added test case for Relay

* Set transaction slot to null in case of failed transaction

* Restrict usage of transaction commands outside of transaction context

* Added handling for Relay responses

* Reverted changes

* Removed unsupported command

* Added dummy arguments

* Codestyle fixes

* Added additional test coverage

* Added CHANGELOG and README entries

* Added missing PR reference

* Missing word

* Fixed README

124 of 136 new or added lines in 11 files covered. (91.18%)

4 existing lines in 1 file now uncovered.

6870 of 7403 relevant lines covered (92.8%)

111.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.59
/src/Transaction/Strategy/NonClusterConnectionStrategy.php
1
<?php
2

3
/*
4
 * This file is part of the Predis package.
5
 *
6
 * (c) 2009-2020 Daniele Alessandri
7
 * (c) 2021-2023 Till Krüss
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12

13
namespace Predis\Transaction\Strategy;
14

15
use Predis\Command\CommandInterface;
16
use Predis\Command\Redis\DISCARD;
17
use Predis\Command\Redis\EXEC;
18
use Predis\Command\Redis\MULTI;
19
use Predis\Command\Redis\UNWATCH;
20
use Predis\Command\Redis\WATCH;
21
use Predis\Connection\NodeConnectionInterface;
22
use Predis\Connection\RelayConnection;
23
use Predis\Connection\Replication\ReplicationInterface;
24
use Predis\Response\ErrorInterface;
25
use Predis\Response\ServerException;
26
use Predis\Transaction\MultiExecState;
27
use Predis\Transaction\Response\BypassTransactionResponse;
28

29
/**
30
 * Defines strategy for connections that operates on non-distributed hash slots.
31
 */
32
abstract class NonClusterConnectionStrategy implements StrategyInterface
33
{
34
    /**
35
     * @var NodeConnectionInterface|ReplicationInterface
36
     */
37
    protected $connection;
38

39
    /**
40
     * @var MultiExecState
41
     */
42
    protected $state;
43

44
    /**
45
     * @param NodeConnectionInterface|ReplicationInterface $connection
46
     */
47
    public function __construct($connection, MultiExecState $state)
42✔
48
    {
49
        $this->connection = $connection;
42✔
50
        $this->state = $state;
42✔
51
    }
52

53
    /**
54
     * {@inheritDoc}
55
     */
56
    public function initializeTransaction(): bool
25✔
57
    {
58
        return 'OK' == $this->executeBypassingTransaction(new MULTI())->getResponse();
25✔
59
    }
60

61
    /**
62
     * {@inheritDoc}
63
     */
64
    public function executeCommand(CommandInterface $command)
31✔
65
    {
66
        if ($this->state->isCAS()) {
31✔
67
            return $this->executeBypassingTransaction($command);
5✔
68
        }
69

70
        return $this->connection->executeCommand($command);
29✔
71
    }
72

73
    /**
74
     * {@inheritDoc}
75
     */
76
    public function executeTransaction()
19✔
77
    {
78
        return $this->executeBypassingTransaction(new EXEC())->getResponse();
19✔
79
    }
80

81
    /**
82
     * {@inheritDoc}
83
     */
84
    public function multi()
3✔
85
    {
86
        return $this->executeBypassingTransaction(new MULTI())->getResponse();
3✔
87
    }
88

89
    /**
90
     * {@inheritDoc}
91
     */
92
    public function watch(array $keys)
7✔
93
    {
94
        $watch = new WATCH();
7✔
95
        $watch->setArguments($keys);
7✔
96

97
        return $this->executeBypassingTransaction($watch)->getResponse();
7✔
98
    }
99

100
    /**
101
     * {@inheritDoc}
102
     */
NEW
103
    public function unwatch()
×
104
    {
NEW
105
        return $this->connection->executeCommand(new UNWATCH());
×
106
    }
107

108
    /**
109
     * {@inheritDoc}
110
     */
111
    public function discard()
9✔
112
    {
113
        return $this->executeBypassingTransaction(new DISCARD())->getResponse();
9✔
114
    }
115

116
    /**
117
     * Executes a Redis command bypassing the transaction logic.
118
     *
119
     * @param  CommandInterface          $command
120
     * @return BypassTransactionResponse
121
     * @throws ServerException
122
     */
123
    protected function executeBypassingTransaction(CommandInterface $command): BypassTransactionResponse
29✔
124
    {
125
        try {
126
            $response = $this->connection->executeCommand($command);
29✔
NEW
127
        } catch (ServerException $exception) {
×
NEW
128
            if (!$this->connection instanceof RelayConnection) {
×
NEW
129
                throw $exception;
×
130
            }
131

NEW
132
            if (strcasecmp($command->getId(), 'EXEC') != 0) {
×
NEW
133
                throw $exception;
×
134
            }
135

NEW
136
            if (!strpos($exception->getMessage(), 'RELAY_ERR_REDIS')) {
×
NEW
137
                throw $exception;
×
138
            }
139

NEW
140
            return new BypassTransactionResponse(null);
×
141
        }
142

143
        if ($response instanceof ErrorInterface) {
29✔
144
            throw new ServerException($response->getMessage());
2✔
145
        }
146

147
        return new BypassTransactionResponse($response);
29✔
148
    }
149
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc