Skip to content

Commit 360b904

Browse files
authored
Fix: Restore $recordsModified state if its value has not been changed (#12)
* Feat: Introduce ApplyingJobInitialization class * Test: Add tests for ApplyinJobInitialization
1 parent f3e27c0 commit 360b904

25 files changed

+632
-91
lines changed

src/ApplyingJobInitialization.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
namespace Mpyw\LaravelCachedDatabaseStickiness;
4+
5+
use Illuminate\Database\ConnectionInterface;
6+
use Illuminate\Database\DatabaseManager;
7+
use Illuminate\Queue\Events\JobProcessing;
8+
use Mpyw\LaravelCachedDatabaseStickiness\Events\ConnectionCreated;
9+
use Mpyw\LaravelCachedDatabaseStickiness\JobInitializers\JobInitializerInterface;
10+
11+
class ApplyingJobInitialization
12+
{
13+
/**
14+
* @var \Mpyw\LaravelCachedDatabaseStickiness\StickinessManager
15+
*/
16+
protected $stickiness;
17+
18+
/**
19+
* @var \Illuminate\Database\DatabaseManager
20+
*/
21+
protected $db;
22+
23+
/**
24+
* @var \Mpyw\LaravelCachedDatabaseStickiness\JobInitializers\JobInitializerInterface
25+
*/
26+
protected $job;
27+
28+
/**
29+
* @var bool[]
30+
*/
31+
protected $recordsModifiedStates = [];
32+
33+
/**
34+
* ApplyingJobInitialization constructor.
35+
*
36+
* @param \Mpyw\LaravelCachedDatabaseStickiness\StickinessManager $stickiness
37+
* @param \Illuminate\Database\DatabaseManager $db
38+
* @param \Mpyw\LaravelCachedDatabaseStickiness\JobInitializers\JobInitializerInterface $initializer
39+
*/
40+
public function __construct(StickinessManager $stickiness, DatabaseManager $db, JobInitializerInterface $initializer)
41+
{
42+
$this->stickiness = $stickiness;
43+
$this->db = $db;
44+
$this->job = $initializer;
45+
}
46+
47+
/**
48+
* Initialize database stickiness state on already resolved connections before processing each job.
49+
*
50+
* @param \Illuminate\Queue\Events\JobProcessing $event
51+
* @return $this
52+
*/
53+
public function initializeOnResolvedConnections(JobProcessing $event)
54+
{
55+
foreach ($this->db->getConnections() as $connection) {
56+
/* @var \Illuminate\Database\Connection|\Illuminate\Database\ConnectionInterface $connection */
57+
$this->recordsModifiedStates[$connection->getName()] = $this->stickiness->getRecordsModified($connection);
58+
}
59+
60+
$this->job->initializeOnResolvedConnections($event);
61+
62+
return $this;
63+
}
64+
65+
/**
66+
* Initialize database stickiness state on newly created connection before processing each job.
67+
*
68+
* @param \Illuminate\Queue\Events\JobProcessing $jobProcessingEvent
69+
* @param \Mpyw\LaravelCachedDatabaseStickiness\Events\ConnectionCreated $connectionCreatedEvent
70+
* @return $this
71+
*/
72+
public function initializeOnNewConnection(JobProcessing $jobProcessingEvent, ConnectionCreated $connectionCreatedEvent)
73+
{
74+
$connection = $connectionCreatedEvent->connection;
75+
76+
$this->recordsModifiedStates[$connection->getName()] = $this->stickiness->getRecordsModified($connection);
77+
78+
$this->job->initializeOnNewConnection($jobProcessingEvent, $connectionCreatedEvent);
79+
80+
return $this;
81+
}
82+
83+
/**
84+
* Avoid revoking stickiness state initialization when DB::recordsHaveBeenModified() called on the Job execution.
85+
*
86+
* @param \Illuminate\Database\Connection|\Illuminate\Database\ConnectionInterface $connection
87+
* @return $this
88+
*/
89+
public function dontRevokeEffectsOn(ConnectionInterface $connection)
90+
{
91+
unset($this->recordsModifiedStates[$connection->getName()]);
92+
93+
return $this;
94+
}
95+
96+
/**
97+
* Revoke database stickiness state initialization after processing each job.
98+
*/
99+
public function __destruct()
100+
{
101+
foreach ($this->db->getConnections() as $connection) {
102+
/* @var \Illuminate\Database\Connection|\Illuminate\Database\ConnectionInterface $connection */
103+
if (null !== $state = $this->recordsModifiedStates[$connection->getName()] ?? null) {
104+
$this->stickiness->setRecordsModified($connection, $state);
105+
}
106+
}
107+
}
108+
}

src/StickinessEventListener.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ class StickinessEventListener
2121
*/
2222
protected $currentJobProcessingEvent;
2323

24+
/**
25+
* @var \Mpyw\LaravelCachedDatabaseStickiness\ApplyingJobInitialization
26+
*/
27+
protected $currentJobInitialization;
28+
2429
/**
2530
* StickinessEventListener constructor.
2631
*
@@ -38,7 +43,8 @@ public function __construct(StickinessManager $stickiness)
3843
*/
3944
public function onJobProcessing(JobProcessing $event): void
4045
{
41-
$this->stickiness->initializeStickinessState($this->currentJobProcessingEvent = $event);
46+
$this->currentJobProcessingEvent = $event;
47+
$this->currentJobInitialization = $this->stickiness->startInitializingJob($event);
4248
}
4349

4450
/**
@@ -49,6 +55,7 @@ public function onJobProcessing(JobProcessing $event): void
4955
public function onJobProcessed(JobProcessed $event): void
5056
{
5157
$this->currentJobProcessingEvent = null;
58+
$this->currentJobInitialization = null;
5259
}
5360

5461
/**
@@ -59,6 +66,7 @@ public function onJobProcessed(JobProcessed $event): void
5966
public function onJobExceptionOccurred(JobExceptionOccurred $event): void
6067
{
6168
$this->currentJobProcessingEvent = null;
69+
$this->currentJobInitialization = null;
6270
}
6371

6472
/**
@@ -69,6 +77,7 @@ public function onJobExceptionOccurred(JobExceptionOccurred $event): void
6977
public function onJobFailed(JobFailed $event): void
7078
{
7179
$this->currentJobProcessingEvent = null;
80+
$this->currentJobInitialization = null;
7281
}
7382

7483
/**
@@ -78,8 +87,8 @@ public function onJobFailed(JobFailed $event): void
7887
*/
7988
public function onConnectionCreated(ConnectionCreated $event): void
8089
{
81-
if ($this->currentJobProcessingEvent) {
82-
$this->stickiness->initializeStickinessState($this->currentJobProcessingEvent, $event);
90+
if ($this->currentJobProcessingEvent && $this->currentJobInitialization) {
91+
$this->currentJobInitialization->initializeOnNewConnection($this->currentJobProcessingEvent, $event);
8392
}
8493

8594
$this->stickiness->resolveRecordsModified($event->connection);
@@ -92,6 +101,10 @@ public function onConnectionCreated(ConnectionCreated $event): void
92101
*/
93102
public function onRecordsHaveBeenModified(RecordsHaveBeenModified $event): void
94103
{
104+
if ($this->currentJobInitialization) {
105+
$this->currentJobInitialization->dontRevokeEffectsOn($event->connection);
106+
}
107+
95108
$this->stickiness->markAsModified($event->connection);
96109
}
97110
}

src/StickinessManager.php

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
use Illuminate\Contracts\Container\Container;
66
use Illuminate\Database\ConnectionInterface;
7+
use Illuminate\Database\DatabaseManager;
78
use Illuminate\Queue\Events\JobProcessing;
8-
use Mpyw\LaravelCachedDatabaseStickiness\Events\ConnectionCreated;
99
use Mpyw\LaravelCachedDatabaseStickiness\JobInitializers\JobInitializerInterface;
1010
use Mpyw\LaravelCachedDatabaseStickiness\StickinessResolvers\StickinessResolverInterface;
1111
use ReflectionProperty;
@@ -16,23 +16,25 @@
1616
class StickinessManager
1717
{
1818
/**
19-
* @var \Illuminate\Database\DatabaseManager
19+
* @var \Illuminate\Contracts\Container\Container
2020
*/
21-
protected $db;
21+
protected $container;
2222

2323
/**
24-
* @var \Illuminate\Contracts\Container\Container
24+
* @var \Illuminate\Database\DatabaseManager
2525
*/
26-
protected $container;
26+
protected $db;
2727

2828
/**
2929
* StickinessManager constructor.
3030
*
3131
* @param \Illuminate\Contracts\Container\Container $container
32+
* @param \Illuminate\Database\DatabaseManager $db
3233
*/
33-
public function __construct(Container $container)
34+
public function __construct(Container $container, DatabaseManager $db)
3435
{
3536
$this->container = $container;
37+
$this->db = $db;
3638
}
3739

3840
/** @noinspection PhpDocMissingThrowsInspection */
@@ -110,20 +112,18 @@ public function isRecentlyModified(ConnectionInterface $connection): bool
110112
return $this->stickinessResolver()->isRecentlyModified($connection);
111113
}
112114

115+
/** @noinspection PhpDocMissingThrowsInspection */
116+
113117
/**
114-
* Initialize database stickiness state before processing each job.
118+
* Start Initializing database stickiness states before processing each job.
115119
*
116-
* @param \Illuminate\Queue\Events\JobProcessing $jobProcessingEvent
117-
* @param null|\Mpyw\LaravelCachedDatabaseStickiness\Events\ConnectionCreated $connectionCreatedEvent
120+
* @param \Illuminate\Queue\Events\JobProcessing $event
121+
* @return \Mpyw\LaravelCachedDatabaseStickiness\ApplyingJobInitialization
118122
*/
119-
public function initializeStickinessState(JobProcessing $jobProcessingEvent, ?ConnectionCreated $connectionCreatedEvent = null): void
123+
public function startInitializingJob(JobProcessing $event): ApplyingJobInitialization
120124
{
121-
$initializer = $this->jobInitializer();
122-
$initializer->initializeOnResolvedConnections($jobProcessingEvent);
123-
124-
if ($connectionCreatedEvent) {
125-
$initializer->initializeOnNewConnection($jobProcessingEvent, $connectionCreatedEvent);
126-
}
125+
return (new ApplyingJobInitialization($this, $this->db, $this->jobInitializer()))
126+
->initializeOnResolvedConnections($event);
127127
}
128128

129129
/** @noinspection PhpDocMissingThrowsInspection */

0 commit comments

Comments
 (0)