Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
DbFactory
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 6
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 forcePrimary
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getDB
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 getLB
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getWikiDB
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
 waitForReplicas
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace Flow;
4
5use Wikimedia\Rdbms\DBReplicationWaitError;
6use Wikimedia\Rdbms\IDatabase;
7use Wikimedia\Rdbms\IReadableDatabase;
8use Wikimedia\Rdbms\LBFactory;
9
10/**
11 * All classes within Flow that need to access the Flow db will go through
12 * this class.  Having it separated into an object greatly simplifies testing
13 * anything that needs to talk to the database.
14 *
15 * The factory receives, in its constructor, the wiki name and cluster name
16 * that Flow-specific data is stored on.  Multiple wiki's can and should be
17 * using the same wiki name and cluster to share Flow-specific data. These values
18 * are used.
19 *
20 * There are also get getWikiLB and getWikiDB for the main wiki database.
21 */
22class DbFactory {
23    /**
24     * @var string|false Wiki ID, or false for the current wiki
25     */
26    protected $wiki;
27
28    /**
29     * @var string|false External storage cluster, or false for core
30     */
31    protected $cluster;
32
33    /**
34     * @var bool When true only DB_PRIMARY will be returned
35     */
36    protected $forcePrimary = false;
37
38    /**
39     * @param LBFactory $lbFactory
40     * @param string|false $wiki Wiki ID, or false for the current wiki
41     * @param string|false $cluster External storage cluster, or false for core
42     */
43    public function __construct(
44        private readonly LBFactory $lbFactory,
45        $wiki,
46        $cluster,
47    ) {
48        $this->wiki = $wiki;
49        $this->cluster = $cluster;
50
51        // Ensure maintenance scripts do not encounter replication errors
52        if ( MW_ENTRY_POINT === 'cli' ) {
53            $this->forcePrimary();
54        }
55    }
56
57    public function forcePrimary() {
58        $this->forcePrimary = true;
59    }
60
61    /**
62     * Gets a database connection for the Flow-specific database.
63     *
64     * @param int $db index of the connection to get.  DB_PRIMARY|DB_REPLICA.
65     * @return IDatabase|IReadableDatabase
66     */
67    public function getDB( $db ) {
68        return $this->getLB()->getConnection( $this->forcePrimary ? DB_PRIMARY : $db, [], $this->wiki );
69    }
70
71    /**
72     * Gets a load balancer for the Flow-specific database.
73     *
74     * @return \Wikimedia\Rdbms\ILoadBalancer
75     */
76    private function getLB() {
77        if ( $this->cluster !== false ) {
78            return $this->lbFactory->getExternalLB( $this->cluster );
79        } else {
80            return $this->lbFactory->getMainLB( $this->wiki );
81        }
82    }
83
84    /**
85     * Gets a database connection for the main wiki database.  Mockable version of wfGetDB.
86     *
87     * @param int $db index of the connection to get.  DB_PRIMARY|DB_REPLICA.
88     * @param string|bool $wiki The wiki ID, or false for the current wiki
89     * @return IDatabase|IReadableDatabase
90     */
91    public function getWikiDB( $db, $wiki = false ) {
92        return $this->lbFactory->getMainLB( $wiki )->getConnection( $this->forcePrimary ? DB_PRIMARY : $db, [], $wiki );
93    }
94
95    /**
96     * Wait for the replicas of the Flow database
97     */
98    public function waitForReplicas() {
99        try {
100            $this->lbFactory->waitForReplication( [
101                'wiki' => $this->wiki,
102                'cluster' => $this->cluster,
103                'ifWritesSince' => false
104            ] );
105        } catch ( DBReplicationWaitError ) {
106        }
107    }
108
109}