Make DBConnRef enforce the DB domain selected during its lifetime
and allow more nested and successive use of the same connection handle
via DBConnRef. This can avoid extra connections in some cases where
getConnection()/getConnectionRef() is used.
Also:
* Reduce the number of connection pools arrays from six to two
* Merge getLocalConnection()/getForeignConnection() into one method
* Expand various related code comments
Since LoadBalancer::getReadOnlyReason() no longer user the local domain
but rather DOMAIN_ANY, it should not result in "USE" errors if the local
domain does not have a database on the server.
This version of the patch removes the unused reuseConnectionInternal()
method (the method was previously added back to the patch by mistake).
Bug: T226595
Change-Id: I62502f4de4f86a54f25be1699c4d1a1c1baee60b
This effects:
* LoadBalancer::getReadOnlyReason()
* LoadBalancer::getLaggedReplicaMode()
* LoadBalancer::isPrimaryRunningReadOnly()
* LoadBalancer::getRandomNonLagged()
The lag/read-only mode is designed to be tracked per-server. The DB domain
is not useful here, and passing one complicates callers, causing needless
cache fragmentation, and cause can errors when a foreign LoadBalancer falls
back (or is provided) a local DB domain (which might not reside on the server).
Clarified some related "server" vs "DB" terminology in comments.
Bug: T318904
Change-Id: I3e09c1915d012db36be1bc505e00dcb0603fd388
Remove most `@throws` as these can't happen on getConnection anymore
because we use lazy connections now.
Remove reference to "live" as this is no longer relevant to callers.
Remove reference to "reference" except for methods that are explicitly
typed as returning DBConnRef.
Bug: T255493
Change-Id: I5fc42913cd59a35ee9478a538fa4dfd455f55cb1
* Document what the LBFactory/LoadBalancer (sub)classes do.
* Move useful descriptions from file doc to class doc so that we don't
pointlessly maintain it in two places, and to allow for the file
block to be consistently visually ignored instead of sometimes
containing useful information.
This patch removes various non-applicable or unrelated descriptions
from the file block that were blindly copy-pasted, thus proving my
point. It also removes two duplicate/clashing definition of the
'Database' defgroup. Keeping only the primary one in IDatabase.php.
* Move ingroup tag to class block, as indexing the source file
in Doxygen creates noise in the navigation sidebar and does not
add add any benefit.
* Fix dead-end reference to a sqlite/README. I'll rework this
in a later patch.
Change-Id: Iad0e67d766f4a7d5b97e7a471b49f2d8e60c506b
Change type bool in union types to false where true is not allowed
Add false to DatabaseSqlite::getFulltextSearchModule
Change-Id: I1199b261c4e5c3f6ff184c756f46f2650b16b0c9
This would simplify the code for its users a lot.
Bug: T255493
Depends-On: I6ab4440a13f4682dd3a6e9cfc6c629222fbeab8a
Change-Id: I6e7544763bde56fc1e19de0358b71ba984a978ca
Callback style iteration made sense before generators existed, but
generators make for simpler code. The "call method" variants made
sense before closures existed but defeat static analysis.
So, in LBFactory:
* Add ILBFactory::getAllLBs()
* Deprecate ILBFactory::forEachLB()
* Remove LBFactory::forEachLBCallMethod(), was protected.
* Add LBFactory::getLBsForOwner(), which is protected and has the
internal interface in @return. Adding a new abstract method breaks
Wikibase tests despite LBFactory not being stable to extend.
* Migrate callers. Generators allow you to return/break from the middle
of the loop, which implies a little rearrangement for some callers.
In LoadBalancer, connections supposedly of type IDatabase were
routinely type-hinted as Database in closure parameters so that methods
could be called that were not in the interface. So it's convenient to
get rid of public iteration methods entirely in favour of private
methods returning Database[].
* Hard-deprecate ILoadBalancerForOwner::forEachOpenConnection()
and replace it with a private generator method since nothing called
it externally except for core tests.
* Hard-deprecate ILoadBalancerForOwner::forEachOpenPrimaryConnection()
and replace it with a private generator. DeferredUpdates needed it for
iterating over IDatabase::explicitTrxActive(), so add
ILoadBalancer::explicitTrxActive() as a replacement.
* Replace private method LoadBalancer::forEachOpenReplicaConnection()
with a generator.
Depends-On: If0b382231e27d6d1197fb7b6aef6ab50335df4e5
Change-Id: I64514e77b9bfe737be5b12e1d3c9c49976bb522f
Instance ownership is supposed to protect LoadBalancer and Database
against unauthorized calls to internal methods other than by the owning
LoadBalancer/LBFactory. This seems like unnecessary complexity. It was
introduced for T231443 and T217819, but the link was speculative and in
the end it didn't help to fix or isolate those bugs. Since then it has
caused a production error (T303885) and an intermittent CI failure
(T292239).
Instead, split the ILoadBalancer interface, introducing
ILoadBalancerForOwner, which contains the methods which are only safe
to call by LBFactory or by the caller of LBFactory::newMainLB(). This
allows phan to statically detect inappropriate calls to internal
methods.
Ownership was used for convenience for two things unrelated to its
original purpose:
* Suppressing calls to ScopedCallback::newScopedIgnoreUserAbort() when
the caller has already called it. But nested calls are apparently
harmless, so I just called it unconditionally.
* Suppressing exceptions from Database::close(). I extended the
behaviour for owned instances to apply to all instances, so even
unowned instances will no longer throw on close.
CodeSearch suggests nothing in extensions is calling these methods with
an owner parameter. One extension (Wikibase) overrides a method with an
owner parameter in a test mock class and so needs to be simultaneously
updated.
Depends-On: Ib03aba9d8f5f05b875a321d00b14483633a636a8
Change-Id: I27ba4973d24d759c88b3868c95e7db875801ca0c
Rename canRecoverFromDisconnect() in order to better describe
its function. Make it use the transaction ID and query walltime
as arguments and return an ERR_* class constant instead of a bool.
Avoid retries of slow queries that yield lost connection errors.
Track session state errors caused by the loss of named locks or
temp tables (e.g. during connection loss). Such errors will prevent
further queries except for rollback() and flushSession(), which must
be issued to resolve the error.
Add flushPrimarySessions() methods to LBFactory/LoadBalancer
and use it in places where session state loss is meant to be
safely aknowledged.
Change-Id: I60532f86e629c83b357d4832d1963eca17752944
We really don't need this complexity and it prevents us from improving
connection management.
MaintainableDatabase should stay but the connection ref shouldn't.
Bug: T255493
Change-Id: I867301dc7fa07cac298f8faba9cf82ca4617f50e
Rename canRecoverFromDisconnect() in order to better describe
its function. Make it use the transaction ID and query walltime
as arguments and return an ERR_* class constant instead of a bool.
Avoid retries of slow queries that yield lost connection errors.
Add methods and class constants to track session state errors
caused by the loss of named locks or temp tables. Such errors can
be resolved by a "session flush" method.
Make assertQueryIsCurrentlyAllowed() better distinguish ROLLBACK
queries from ROLLBACK TO SAVEPOINT queries. For some scenarios,
only full tranasction ROLLBACK queries should be allowed.
Add flushSession() method to Database and flushPrimarySessions()
methods to LBFactory/LoadBalancer.
Also:
* Rename wasKnownStatementRollbackError() and make it take the
error number as an argument, similar to wasConnectionError().
Add mysql error codes for query timeouts since they only cause
statement rollbacks.
* Rename wasConnectionError() and mark it as protected. This is an
internal method with no outside callers.
* Rename wasQueryTimeout(), remove some HHVM-specific code, and
simplify the arguments.
* Make executeQuery() use a for loop for the query retry logic
to reduce code duplication.
* Move the error state setting logic in executeQueryAttempt() up
in order to reduce code duplication.
* Move the beginIfImplied() call in executeQueryAttempt() up to the
retry loop in executeQuery(). This narrows the executeQueryAttempt()
concerns to sending a single query and updating tracking fields.
* Make closeConnection() and doHandleSessionLossPreconnect() in
DatabaseSqlite more consistent with the base class by releasing named locks.
* Mark trxStatus() as @internal.
Bug: T281451
Bug: T293859
Change-Id: I200f90e413b8a725828745f81925b54985c72180
The implementation returns bool, change the docs to reflect that.
Needs adjust of a bitwise or
Found by phan strict checks
Change-Id: I0a586c70b6e8a7fbad609cfad1a782be8af9d1b4
The renaming of master -> primary
Also removing a function with similar name that were unused and
removed from the interface already.
Bug: T299392
Change-Id: Ia10cd7eacb95d6eabc370dfe37c23121b7c07772
See full rationale at I59068cfed10aabf6c6002f9e9312a6ef6e7e9441.
Using IDatabase for now instead of DBConnRef for better BC.
Change-Id: Ie75aaf46ba91779e8706b10efeefa9580857f489
These not only make the code more robust, but also help a lot when
writing unit tests: if a method is return-typehinted and its class is
mocked, the mock method will automatically return a mock of its declared
return type. Otherwise it will return null, and developers are forced to
manually mock the method if the return value is used by the SUT in a way
that doesn't accept null.
Depends-On: I628fcb1807133390c7b9b47984f512f5b1ae58d0
Depends-On: I7080bc505f5838b2f51a368da562104e206063b0
Change-Id: I59068cfed10aabf6c6002f9e9312a6ef6e7e9441
Use CONN_SILENCE_ERRORS similar to other internal callers of
getServerConnection(). Also, make isMasterRunningReadOnly() handle
the isOpen() edge case. Since the invoked method should probably
throw a DBError in that case, add a FIXME comment.
Remove "lockTSE" option, which was not useful here since there
are no explicit purges.
Also improve ILoadBalaner::getServerConnection() documentation.
Change-Id: I51dc14a6261fa646106a9fadce3baddb860fd090
Make getServer() always return a string, as documented, even with new
Database::NEW_UNCONNECTED handles that have yet to call open(). If the
'host' parameter to __construct() is ''/null, getServer() now returns
'localhost' instead of null. This avoids problems like fatal errors in
calls to TransactionProfiler::recordConnection().
Use Database constants for "connectionParams" field keys for better
static analysis.
Also:
* Add Database::getServerName() method that returns "readable" server
names in the style of LoadBalancer::getServerName(). Note that the
"hostName" field is already passed in from LoadBalancer.
* Migrate most getServer() callers to getServerName() for easier
debugging and more readable logging.
* Also, normalize Database/LoadBalancer SPI logging context to use
"db_server" and reduce logging code duplication in LoadBalancer.
Bug: T277056
Change-Id: I00ed4049ebb45edab1ea07561c47e226a423ea3b