-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMasterSlaveConnection.php
More file actions
153 lines (134 loc) · 3.93 KB
/
Copy pathMasterSlaveConnection.php
File metadata and controls
153 lines (134 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?php
namespace Bdf\Prime\Connection;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Result;
use LogicException;
/**
* MasterSlaveConnection
*
* The master / slave connection is a connection to a master server with a connection wrapper to a slave server.
* Only method SimpleConnection#executeQuery will be redirect to the salve.
*
* SimpleConnection#quote also use slave.
*
* Becareful those methods are used on master:
*
* SimpleConnection#prepare
* SimpleConnection#query
*
* @package Bdf\Prime\Connection
*/
class MasterSlaveConnection extends SimpleConnection implements SubConnectionManagerInterface
{
/**
* The connection specifically for read operations
*
* This connection is used only for the method SimpleConnection#executeQuery
*
* @var SimpleConnection
*/
private $readConnection;
/**
* Force the read on master
*
* @var boolean
*/
private $force = false;
/**
* Initializes a new instance of the Connection class.
*
* Here's a read connection configuration
*
* @example
*
* $conn = DriverManager::getConnection([
* 'driver' => 'pdo_mysql',
* 'user' => '',
* 'password' => '',
* 'host' => '',
* 'dbname' => '',
* 'read' => [
* 'user' => 'slave',
* 'password' => '',
* 'host' => '',
* 'dbname' => '',
* ]
* ]);
*
* @param array $params The connection parameters.
* @param \Doctrine\DBAL\Driver $driver The driver to use.
* @param \Doctrine\DBAL\Configuration|null $config The configuration, optional.
* @param \Doctrine\Common\EventManager|null $eventManager The event manager, optional.
*/
public function __construct(array $params, Driver $driver, ?Configuration $config = null, ?EventManager $eventManager = null)
{
if (!isset($params['read'])) {
throw new LogicException('Master/slave connection needs readable connection in parameters');
}
$this->readConnection = $params['read'];
parent::__construct($params, $driver, $config, $eventManager);
}
/**
* Get the read connection
*
* @return SimpleConnection
*/
public function getReadConnection()
{
return $this->readConnection;
}
/**
* {@inheritdoc}
*/
public function getConnection(string $name): ConnectionInterface
{
if ($name === 'read') {
return $this->readConnection;
}
// Force the read on master if it is the awaiting connection
if ($name === 'master') {
return $this->force();
}
throw new LogicException('The sub connection "'.$name.'" is unknown in the master / slave connection');
}
/**
* Force next read on master connection once
* This flag will change after the execution of method executeQuery
*
* @return $this
*/
public function force()
{
$this->force = true;
return $this;
}
/**
* {@inheritdoc}
*/
public function executeQuery(string $sql, array $params = [], $types = [], ?QueryCacheProfile $qcp = null): Result
{
if ($this->getTransactionNestingLevel() <= 0 && $this->force !== true) {
return $this->readConnection->executeQuery($sql, $params, $types, $qcp);
}
$this->force = false;
return parent::executeQuery($sql, $params, $types, $qcp);
}
/**
* {@inheritdoc}
*/
public function quote($value, $type = null)
{
return $this->readConnection->quote($value, $type);
}
/**
* {@inheritdoc}
*/
public function close(): void
{
parent::close();
$this->readConnection->close();
}
}