Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | n/a |
0 / 0 |
n/a |
0 / 0 |
CRAP | n/a |
0 / 0 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | */ |
20 | namespace Wikimedia\Rdbms; |
21 | |
22 | use Generator; |
23 | use InvalidArgumentException; |
24 | |
25 | /** |
26 | * Manager of ILoadBalancer objects and, indirectly, IDatabase connections |
27 | * |
28 | * Each Load balancer instances corresponds to a specific database cluster. |
29 | * A "cluster" is the set of database servers that manage a given dataset. |
30 | * |
31 | * The "core" clusters are meant to colocate the most basic and highly relational application |
32 | * data for one or more "sister projects" managed by this site. This allows for highly flexible |
33 | * queries. Each project is identified by a database domain. Note that if there are several |
34 | * projects stored on a cluster, then the cluster dataset is a superset of the dataset for each |
35 | * of those projects. |
36 | * |
37 | * The "external" clusters are meant to provide places for bulk text storage, to colocate bulky |
38 | * relational data from specific modules, and to colocate data from cross-project modules such |
39 | * as authentication systems. An external cluster can have a database/schema for each project. |
40 | * |
41 | * @see ILoadBalancer |
42 | * |
43 | * @ingroup Database |
44 | * @since 1.28 |
45 | */ |
46 | interface ILBFactory extends IConnectionProvider { |
47 | /** Idiom for "no special shutdown flags" */ |
48 | public const SHUTDOWN_NORMAL = 0; |
49 | /** Do not save "session consistency" DB replication positions */ |
50 | public const SHUTDOWN_NO_CHRONPROT = 1; |
51 | |
52 | /** @var string Default main cluster name (do not change this) */ |
53 | public const CLUSTER_MAIN_DEFAULT = 'DEFAULT'; |
54 | |
55 | /** |
56 | * Sub-classes may extend the required keys in $conf with additional parameters |
57 | * |
58 | * @param array $conf Array with keys: |
59 | * - localDomain: A DatabaseDomain or database domain ID string |
60 | * - virtualDomains: List of virtual database domain ID strings [optional]. |
61 | * These can be passed to {@see ILBFactory::getPrimaryDatabase()} and |
62 | * {@see ILBFactory::getReplicaDatabase()}, with the actual cluster and database |
63 | * domain being automatically resolved via "virtualDomainsMapping". Virtual database |
64 | * domains not defined there will resolve to the local database domain. |
65 | * - virtualDomainsMapping: Map of (virtual database domain ID => config map) [optional]. |
66 | * Each config map has a "db" key and an optional "cluster" key. The "db" key specifies |
67 | * the actual database domain configured for use, with false indicating that the local |
68 | * database domain is configured for use. The "cluster" key, if provided, specifies the |
69 | * name of the external cluster configured for use, otherwise, the main cluster for the |
70 | * actual database domain will be used. |
71 | * - chronologyProtector: ChronologyProtector instance [optional] |
72 | * - readOnlyReason: Reason the primary server is read-only (false if not) |
73 | * - srvCache: BagOStuff instance for server cache [optional] |
74 | * - cpStash: BagOStuff instance for ChronologyProtector store [optional]. |
75 | * See [ChronologyProtector requirements](@ref ChronologyProtector-storage-requirements). |
76 | * - wanCache: WANObjectCache instance [optional] |
77 | * - cliMode: Whether the execution context is a CLI script [optional] |
78 | * - profiler: Callback that takes a profile section name and returns a ScopedCallback |
79 | * that ends the profile section in its destructor [optional] |
80 | * - trxProfiler: TransactionProfiler instance [optional] |
81 | * - logger: PSR-3 logger instance [optional] |
82 | * - errorLogger: Callback that takes an Exception and logs it [optional] |
83 | * - deprecationLogger: Callback to log a deprecation warning [optional] |
84 | * - secret: Secret string to use for HMAC hashing [optional] |
85 | * - criticalSectionProvider: CriticalSectionProvider instance [optional] |
86 | */ |
87 | public function __construct( array $conf ); |
88 | |
89 | /** |
90 | * Close all connections and make further attempts to open connections result in DBAccessError |
91 | * |
92 | * This only applies to the tracked load balancer instances. |
93 | * |
94 | * @see ILoadBalancer::disable() |
95 | */ |
96 | public function destroy(); |
97 | |
98 | /** |
99 | * Reload the configuration if necessary. |
100 | * This may or may not have any effect. |
101 | */ |
102 | public function autoReconfigure(): void; |
103 | |
104 | /** |
105 | * Get the local (and default) database domain ID of connection handles |
106 | * |
107 | * @see DatabaseDomain |
108 | * @return string Database domain ID; this specifies DB name, schema, and table prefix |
109 | * @since 1.32 |
110 | */ |
111 | public function getLocalDomainID(); |
112 | |
113 | /** |
114 | * Close all connections and redefine the local database domain |
115 | * |
116 | * This only applies to the tracked load balancer instances. |
117 | * |
118 | * This method is only intended for use with schema creation or integration testing |
119 | * |
120 | * @param DatabaseDomain|string $domain |
121 | * @since 1.33 |
122 | */ |
123 | public function redefineLocalDomain( $domain ); |
124 | |
125 | /** |
126 | * Get the tracked load balancer instance for a given domain. |
127 | * |
128 | * If no tracked instances exists, then one will be instantiated. |
129 | * |
130 | * This method accepts virtual domains |
131 | * ({@see \MediaWiki\MainConfigSchema::VirtualDomainsMapping}). |
132 | * |
133 | * @since 1.43 |
134 | * @param string|false $domain Domain ID, or false for the current domain |
135 | * @return ILoadBalancer |
136 | */ |
137 | public function getLoadBalancer( $domain = false ): ILoadBalancer; |
138 | |
139 | /** |
140 | * Create a new load balancer instance for the main cluster that handles the given domain |
141 | * |
142 | * The resulting object will be untracked and the caller is responsible for cleaning it up. |
143 | * Database replication positions will not be saved by ChronologyProtector. |
144 | * |
145 | * This method is for only advanced usage and callers should almost always use |
146 | * getMainLB() instead. This method can be useful when a table is used as a key/value |
147 | * store. In that cases, one might want to query it in autocommit mode (DBO_TRX off) |
148 | * but still use DBO_TRX transaction rounds on other tables. |
149 | * |
150 | * @note The local/default database domain used by the load balancer instance will |
151 | * still inherit from this ILBFactory instance, regardless of the $domain parameter. |
152 | * |
153 | * @param string|false $domain Domain ID, or false for the current domain |
154 | * @return ILoadBalancerForOwner |
155 | */ |
156 | public function newMainLB( $domain = false ): ILoadBalancerForOwner; |
157 | |
158 | /** |
159 | * Get the tracked load balancer instance for the main cluster that handles the given domain |
160 | * |
161 | * If no tracked instances exists, then one will be instantiated |
162 | * |
163 | * @note The local/default database domain used by the load balancer instance will |
164 | * still inherit from this ILBFactory instance, regardless of the $domain parameter. |
165 | * |
166 | * @param string|false $domain Domain ID, or false for the current domain |
167 | * @return ILoadBalancer |
168 | */ |
169 | public function getMainLB( $domain = false ): ILoadBalancer; |
170 | |
171 | /** |
172 | * Create a new load balancer instance for an external cluster |
173 | * |
174 | * The resulting object will be untracked and the caller is responsible for cleaning it up. |
175 | * Database replication positions will not be saved by ChronologyProtector. |
176 | * |
177 | * This method is for only advanced usage and callers should almost always use |
178 | * getExternalLB() instead. This method can be useful when a table is used as a |
179 | * key/value store. In that cases, one might want to query it in autocommit mode |
180 | * (DBO_TRX off) but still use DBO_TRX transaction rounds on other tables. |
181 | * |
182 | * @param string $cluster External cluster name |
183 | * @throws InvalidArgumentException If $cluster is not recognized |
184 | * @return ILoadBalancerForOwner |
185 | */ |
186 | public function newExternalLB( $cluster ): ILoadBalancerForOwner; |
187 | |
188 | /** |
189 | * Get the tracked load balancer instance for an external cluster |
190 | * |
191 | * If no tracked instances exists, then one will be instantiated |
192 | * |
193 | * @param string $cluster External cluster name |
194 | * @throws InvalidArgumentException If $cluster is not recognized |
195 | * @return ILoadBalancer |
196 | */ |
197 | public function getExternalLB( $cluster ): ILoadBalancer; |
198 | |
199 | /** |
200 | * Get the tracked load balancer instances for all main clusters |
201 | * |
202 | * If no tracked instance exists for a cluster, then one will be instantiated |
203 | * |
204 | * Note that default main cluster name is ILoadBalancer::CLUSTER_MAIN_DEFAULT |
205 | * |
206 | * @return ILoadBalancer[] Map of (cluster name => ILoadBalancer) |
207 | * @since 1.29 |
208 | */ |
209 | public function getAllMainLBs(): array; |
210 | |
211 | /** |
212 | * Get the tracked load balancer instances for all external clusters |
213 | * |
214 | * If no tracked instance exists for a cluster, then one will be instantiated |
215 | * |
216 | * @return ILoadBalancer[] Map of (cluster name => ILoadBalancer) |
217 | * @since 1.29 |
218 | */ |
219 | public function getAllExternalLBs(): array; |
220 | |
221 | /** |
222 | * Get all tracked load balancer instances (generator) |
223 | * |
224 | * @return Generator|ILoadBalancer[] |
225 | * @since 1.39 |
226 | */ |
227 | public function getAllLBs(); |
228 | |
229 | /** |
230 | * Prepare all instantiated tracked load balancer instances for shutdown |
231 | * |
232 | * @param int $flags Bit field of ILBFactory::SHUTDOWN_* constants |
233 | * @param callable|null $workCallback Work to mask ChronologyProtector writes |
234 | * @param int|null &$cpIndex Position key write counter for ChronologyProtector [returned] |
235 | * @param string|null &$cpClientId Client ID hash for ChronologyProtector [returned] |
236 | */ |
237 | public function shutdown( |
238 | $flags = self::SHUTDOWN_NORMAL, |
239 | callable $workCallback = null, |
240 | &$cpIndex = null, |
241 | &$cpClientId = null |
242 | ); |
243 | |
244 | /** |
245 | * Commit all replica database server transactions, clearing any REPEATABLE-READ/SSI snapshots |
246 | * |
247 | * This only applies to the instantiated tracked load balancer instances. |
248 | * |
249 | * This is useful for getting rid of stale data from an implicit transaction round |
250 | * |
251 | * @param string $fname Caller name |
252 | */ |
253 | public function flushReplicaSnapshots( $fname = __METHOD__ ); |
254 | |
255 | /** |
256 | * Flush any primary transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set) |
257 | * |
258 | * The DBO_TRX setting will be reverted to the default in each of these methods: |
259 | * - commitPrimaryChanges() |
260 | * - rollbackPrimaryChanges() |
261 | * |
262 | * This only applies to the tracked load balancer instances. |
263 | * |
264 | * This allows for custom transaction rounds from any outer transaction scope. |
265 | * |
266 | * @param string $fname |
267 | * @throws DBTransactionError |
268 | * @since 1.37 |
269 | */ |
270 | public function beginPrimaryChanges( $fname = __METHOD__ ); |
271 | |
272 | /** |
273 | * Commit changes and clear view snapshots on all primary connections |
274 | * |
275 | * This only applies to the instantiated tracked load balancer instances. |
276 | * |
277 | * @param string $fname Caller name |
278 | * @param int $maxWriteDuration abort if more than this much time was spent in write queries |
279 | * @throws DBTransactionError |
280 | * @since 1.37 |
281 | */ |
282 | public function commitPrimaryChanges( $fname = __METHOD__, int $maxWriteDuration = 0 ); |
283 | |
284 | /** |
285 | * Rollback changes on all primary connections |
286 | * |
287 | * This only applies to the instantiated tracked load balancer instances. |
288 | * |
289 | * @param string $fname Caller name |
290 | * @since 1.37 |
291 | */ |
292 | public function rollbackPrimaryChanges( $fname = __METHOD__ ); |
293 | |
294 | /** |
295 | * Release important session-level state (named lock, table locks) as post-rollback cleanup |
296 | * |
297 | * This only applies to the instantiated tracked load balancer instances. |
298 | * |
299 | * This should only be called by application entry point functions, since there must be |
300 | * no chance that a future caller will still be expecting some of the lost session state. |
301 | * |
302 | * @param string $fname Caller name |
303 | * @since 1.38 |
304 | */ |
305 | public function flushPrimarySessions( $fname = __METHOD__ ); |
306 | |
307 | /** |
308 | * Check if an explicit transaction round is active |
309 | * |
310 | * @return bool |
311 | * @since 1.29 |
312 | */ |
313 | public function hasTransactionRound(); |
314 | |
315 | /** |
316 | * Check if transaction rounds can be started, committed, or rolled back right now |
317 | * |
318 | * This can be used as a recursion guard to avoid exceptions in transaction callbacks. |
319 | * |
320 | * @return bool |
321 | * @since 1.32 |
322 | */ |
323 | public function isReadyForRoundOperations(); |
324 | |
325 | /** |
326 | * Determine if any primary connection has pending changes |
327 | * |
328 | * This only applies to the instantiated tracked load balancer instances. |
329 | * |
330 | * @return bool |
331 | * @since 1.37 |
332 | */ |
333 | public function hasPrimaryChanges(); |
334 | |
335 | /** |
336 | * Determine if any lagged replica database server connection was used. |
337 | * |
338 | * This only applies to the instantiated tracked load balancer instances. |
339 | * |
340 | * @return bool |
341 | */ |
342 | public function laggedReplicaUsed(); |
343 | |
344 | /** |
345 | * Determine if any primary connection has pending/written changes from this request |
346 | * |
347 | * This only applies to the instantiated tracked load balancer instances. |
348 | * |
349 | * @param float|null $age How many seconds ago is "recent" [defaults to LB lag wait timeout] |
350 | * @return bool |
351 | */ |
352 | public function hasOrMadeRecentPrimaryChanges( $age = null ); |
353 | |
354 | /** |
355 | * Waits for the replica database server to catch up to the current primary position |
356 | * |
357 | * Use this when updating very large numbers of rows, as in maintenance scripts, to |
358 | * avoid causing too much lag. This is a no-op if there are no replica database servers. |
359 | * |
360 | * By default this waits on all DB clusters actually used in this request. |
361 | * This makes sense when lag being waiting on is caused by the code that does this check. |
362 | * In that case, setting "ifWritesSince" can avoid the overhead of waiting for clusters |
363 | * that were not changed since the last wait check. |
364 | * |
365 | * Never call this function after a large DB write that is *still* in a transaction. |
366 | * It only makes sense to call this after the possible lag inducing changes were committed. |
367 | * |
368 | * This only applies to the instantiated tracked load balancer instances. |
369 | * |
370 | * @param array $opts Optional fields that include: |
371 | * - timeout: Max wait time. Default: 60 seconds for CLI, 1 second for web. |
372 | * - ifWritesSince: Only wait if writes were done since this UNIX timestamp. |
373 | * @return bool True on success, false if a timeout or error occurred while waiting |
374 | */ |
375 | public function waitForReplication( array $opts = [] ); |
376 | |
377 | /** |
378 | * Add a callback to be run in every call to waitForReplication() before waiting |
379 | * |
380 | * Callbacks must clear any transactions that they start. |
381 | * |
382 | * @param string $name Callback name |
383 | * @param callable|null $callback Use null to unset a callback |
384 | */ |
385 | public function setWaitForReplicationListener( $name, callable $callback = null ); |
386 | |
387 | /** |
388 | * Disable the ChronologyProtector on all instantiated tracked load balancer instances |
389 | * |
390 | * This can be called at the start of special API entry points. |
391 | */ |
392 | public function disableChronologyProtection(); |
393 | |
394 | /** |
395 | * Set a new table prefix for the existing local domain ID for testing |
396 | * |
397 | * @param string $prefix |
398 | * @since 1.33 |
399 | */ |
400 | public function setLocalDomainPrefix( $prefix ); |
401 | |
402 | /** |
403 | * Close all connections on instantiated tracked load balancer instances |
404 | * |
405 | * @param string $fname Caller name (e.g. __METHOD__) |
406 | */ |
407 | public function closeAll( $fname = __METHOD__ ); |
408 | |
409 | /** |
410 | * @param string $agent Agent name for query profiling |
411 | */ |
412 | public function setAgentName( $agent ); |
413 | |
414 | /** |
415 | * Whether it has streaming replica servers. |
416 | * |
417 | * @since 1.41 |
418 | * @return bool |
419 | */ |
420 | public function hasStreamingReplicaServers(); |
421 | |
422 | /** |
423 | * Set the default timeout for replication wait checks |
424 | * |
425 | * @param int $seconds Timeout, in seconds |
426 | * @return int The previous default timeout |
427 | * @since 1.35 |
428 | */ |
429 | public function setDefaultReplicationWaitTimeout( $seconds ); |
430 | |
431 | /** |
432 | * Make certain table names use their own database, schema, and table prefix |
433 | * when passed into SQL queries pre-escaped and without a qualified database name |
434 | * |
435 | * For example, "user" can be converted to "myschema.mydbname.user" for convenience. |
436 | * Appearances like `user`, somedb.user, somedb.someschema.user will used literally. |
437 | * |
438 | * Calling this twice will completely clear any old table aliases. Also, note that |
439 | * callers are responsible for making sure the schemas and databases actually exist. |
440 | * |
441 | * @param array[] $aliases Map of (table => (dbname, schema, prefix) map) |
442 | * @since 1.31 |
443 | */ |
444 | public function setTableAliases( array $aliases ); |
445 | |
446 | /** |
447 | * Convert certain index names to alternative names before querying the DB |
448 | * |
449 | * Note that this applies to indexes regardless of the table they belong to. |
450 | * |
451 | * This can be employed when an index was renamed X => Y in code, but the new Y-named |
452 | * indexes were not yet built on all DBs. After all the Y-named ones are added by the DBA, |
453 | * the aliases can be removed, and then the old X-named indexes dropped. |
454 | * |
455 | * @param string[] $aliases Map of (index alias => index name) |
456 | * @since 1.31 |
457 | */ |
458 | public function setIndexAliases( array $aliases ); |
459 | |
460 | /** |
461 | * Convert certain database domains to alternative ones |
462 | * |
463 | * This can be used for backwards compatibility logic. |
464 | * |
465 | * @param DatabaseDomain[]|string[] $aliases Map of (domain alias => domain) |
466 | * @since 1.35 |
467 | */ |
468 | public function setDomainAliases( array $aliases ); |
469 | |
470 | /** |
471 | * Get the TransactionProfiler used by this instance |
472 | * |
473 | * @return TransactionProfiler |
474 | * @since 1.35 |
475 | */ |
476 | public function getTransactionProfiler(): TransactionProfiler; |
477 | } |