Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/Database/ReplicaKillSwitch.php @ 18:af1871eacc83
Update to Drupal core 8.7.1
author | Chris Cannam |
---|---|
date | Thu, 09 May 2019 15:33:08 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
17:129ea1e6d783 | 18:af1871eacc83 |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\Core\Database; | |
4 | |
5 use Drupal\Component\Datetime\TimeInterface; | |
6 use Drupal\Core\Site\Settings; | |
7 use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
8 use Symfony\Component\HttpFoundation\Session\SessionInterface; | |
9 use Symfony\Component\HttpKernel\Event\GetResponseEvent; | |
10 use Symfony\Component\HttpKernel\KernelEvents; | |
11 | |
12 /** | |
13 * Provides replica server kill switch to ignore it. | |
14 */ | |
15 class ReplicaKillSwitch implements EventSubscriberInterface { | |
16 | |
17 /** | |
18 * The settings object. | |
19 * | |
20 * @var \Drupal\Core\Site\Settings | |
21 */ | |
22 protected $settings; | |
23 | |
24 /** | |
25 * The time service. | |
26 * | |
27 * @var \Drupal\Component\Datetime\TimeInterface | |
28 */ | |
29 protected $time; | |
30 | |
31 /** | |
32 * The session. | |
33 * | |
34 * @var \Symfony\Component\HttpFoundation\Session\SessionInterface | |
35 */ | |
36 protected $session; | |
37 | |
38 /** | |
39 * Constructs a ReplicaKillSwitch object. | |
40 * | |
41 * @param \Drupal\Core\Site\Settings $settings | |
42 * The settings object. | |
43 * @param \Drupal\Component\Datetime\TimeInterface $time | |
44 * The time service. | |
45 * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session | |
46 * The session. | |
47 */ | |
48 public function __construct(Settings $settings, TimeInterface $time, SessionInterface $session) { | |
49 $this->settings = $settings; | |
50 $this->time = $time; | |
51 $this->session = $session; | |
52 } | |
53 | |
54 /** | |
55 * Denies access to replica database on the current request. | |
56 * | |
57 * @see https://www.drupal.org/node/2286193 | |
58 */ | |
59 public function trigger() { | |
60 $connection_info = Database::getConnectionInfo(); | |
61 // Only set ignore_replica_server if there are replica servers being used, | |
62 // which is assumed if there are more than one. | |
63 if (count($connection_info) > 1) { | |
64 // Five minutes is long enough to allow the replica to break and resume | |
65 // interrupted replication without causing problems on the Drupal site | |
66 // from the old data. | |
67 $duration = $this->settings->get('maximum_replication_lag', 300); | |
68 // Set session variable with amount of time to delay before using replica. | |
69 $this->session->set('ignore_replica_server', $this->time->getRequestTime() + $duration); | |
70 } | |
71 } | |
72 | |
73 /** | |
74 * Checks and disables the replica database server if appropriate. | |
75 * | |
76 * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event | |
77 * The Event to process. | |
78 */ | |
79 public function checkReplicaServer(GetResponseEvent $event) { | |
80 // Ignore replica database servers for this request. | |
81 // | |
82 // In Drupal's distributed database structure, new data is written to the | |
83 // master and then propagated to the replica servers. This means there is a | |
84 // lag between when data is written to the master and when it is available | |
85 // on the replica. At these times, we will want to avoid using a replica | |
86 // server temporarily. For example, if a user posts a new node then we want | |
87 // to disable the replica server for that user temporarily to allow the | |
88 // replica server to catch up. | |
89 // That way, that user will see their changes immediately while for other | |
90 // users we still get the benefits of having a replica server, just with | |
91 // slightly stale data. Code that wants to disable the replica server should | |
92 // use the 'database.replica_kill_switch' service's trigger() method to set | |
93 // 'ignore_replica_server' session flag to the timestamp after which the | |
94 // replica can be re-enabled. | |
95 if ($this->session->has('ignore_replica_server')) { | |
96 if ($this->session->get('ignore_replica_server') >= $this->time->getRequestTime()) { | |
97 Database::ignoreTarget('default', 'replica'); | |
98 } | |
99 else { | |
100 $this->session->remove('ignore_replica_server'); | |
101 } | |
102 } | |
103 } | |
104 | |
105 /** | |
106 * {@inheritdoc} | |
107 */ | |
108 public static function getSubscribedEvents() { | |
109 $events[KernelEvents::REQUEST][] = ['checkReplicaServer']; | |
110 return $events; | |
111 } | |
112 | |
113 } |