Problem/Motivation
Whenever a request is processed, the database.replica_kill_switch
service checks if the replica database should be ignored. The problem is that the event subscriber method \Drupal\Core\Database\ReplicaKillSwitch::checkReplicaServer
always fetches data from the session, which can cause a session to be started when it has already been stopped.
if ($this->session->has('ignore_replica_server')) {
if ($this->session->get('ignore_replica_server') >= $this->time->getRequestTime()) {
Database::ignoreTarget('default', 'replica');
}
else {
$this->session->remove('ignore_replica_server');
}
}
The \Drupal\Core\Database\ReplicaKillSwitch::trigger
has a preflight check that sees if a replica server even exists before setting a session variable. The check method should perform this check as well.
Steps to reproduce
On kernel.terminate
perform a subrequest. The request triggers the replica killswitch check and throws an except due to headers already being sent.
Proposed resolution
Add this check before reaching into the session service and lazy loading/starting a service
$connection_info = Database::getConnectionInfo();
// Only set ignore_replica_server if there are replica servers being used,
// which is assumed if there are more than one.
if (count($connection_info) > 1) {