PluginProbe
ووسلام – همگام سازی ووکامرس و باسلام / 1.10.22
ووسلام – همگام سازی ووکامرس و باسلام v1.10.22
1.10.22 1.10.21 1.10.19 1.10.20 1.10.18 1.10.17 1.10.15 1.10.14 1.10.13 1.10.12 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.2 1.9.1 1.9.0 1.8.8 All 55 releases
← All changes | tests/JobsRunnerTest.php +68 -14 1.10.18 → 1.10.22 View file →
@@ -8,16 +8,21 @@
8 8 class JobsRunnerTest extends TestCase
9 9 {
10 10 private const ASYNC_ACTION = 'sync_basalam_run_jobs_async';
11 11 private const DISPATCH_LOCK = 'sync_basalam_jobs_runner_async_dispatch_lock';
12 + private const IDLE_PROBE_LOCK = 'sync_basalam_jobs_runner_idle_probe_lock';
12 13
13 14 private $originalRequest;
14 15 private $originalCookie;
16 + private $originalWpdb;
17 + private $hadOriginalWpdb;
15 18
16 19 protected function setUp(): void
17 20 {
18 21 $this->originalRequest = $_REQUEST;
19 22 $this->originalCookie = $_COOKIE;
23 + $this->hadOriginalWpdb = array_key_exists('wpdb', $GLOBALS);
24 + $this->originalWpdb = $GLOBALS['wpdb'] ?? null;
20 25
21 26 $_REQUEST = [];
22 27 $_COOKIE = [];
23 28
@@ -23,8 +28,9 @@
23 28
24 29 $GLOBALS['sync_basalam_jobs_runner_test_state'] = [
25 30 'actions' => [],
26 31 'did_actions' => [],
32 + 'current_filter' => '',
27 33 'doing_ajax' => false,
28 34 'transients' => [],
29 35 'transient_reads' => [],
30 36 'transient_writes' => [],
@@ -38,8 +44,14 @@
38 44 {
39 45 $_REQUEST = $this->originalRequest;
40 46 $_COOKIE = $this->originalCookie;
41 47
48 + if ($this->hadOriginalWpdb) {
49 + $GLOBALS['wpdb'] = $this->originalWpdb;
50 + } else {
51 + unset($GLOBALS['wpdb']);
52 + }
53 +
42 54 unset($GLOBALS['sync_basalam_jobs_runner_test_state']);
43 55 }
44 56
45 57 public function testRegistersDispatcherOnShutdownAndNeverOnInit(): void
@@ -48,9 +60,9 @@
48 60 $actions = $this->state()['actions'];
49 61
50 62 self::assertArrayHasKey('shutdown', $actions);
51 63 self::assertSame([$runner, 'maybeDispatchAsyncRequest'], $actions['shutdown'][0]['callback']);
52 - self::assertSame(PHP_INT_MAX, $actions['shutdown'][0]['priority']);
64 + self::assertSame(2, $actions['shutdown'][0]['priority']);
53 65 self::assertSame(1, $actions['shutdown'][0]['accepted_args']);
54 66 self::assertArrayNotHasKey('init', $actions);
55 67
56 68 self::assertSame(
@@ -64,9 +76,9 @@
64 76 $actions['wp_ajax_nopriv_' . self::ASYNC_ACTION][0]['callback']
65 77 );
66 78 }
67 79
68 - public function testDispatchLeaseIsWrittenBeforeQueueProbeAndDispatching(): void
80 + public function testDispatchLeaseIsWrittenOnlyWhenQueueHasWork(): void
69 81 {
70 82 $jobManager = new FakeJobManager([true]);
71 83 $runner = $this->newRunner($jobManager);
72 84
@@ -73,9 +85,9 @@
73 85 $_COOKIE = ['wordpress_test_cookie' => 'cookie-value'];
74 86 $runner->maybeDispatchAsyncRequest();
75 87
76 88 self::assertSame(
77 - ['get_transient', 'set_transient', 'has_pending_jobs', 'remote_post'],
89 + ['get_transient', 'get_transient', 'has_pending_jobs', 'get_transient', 'set_transient', 'remote_post'],
78 90 $this->state()['events']
79 91 );
80 92 self::assertSame([120], $jobManager->timeouts);
81 93 self::assertSame(
@@ -99,22 +111,47 @@
99 111 self::assertSame('test-nonce-for-' . self::ASYNC_ACTION, $requests[0]['args']['body']['nonce']);
100 112 self::assertSame($_COOKIE, $requests[0]['args']['cookies']);
101 113 }
102 114
103 - public function testEmptyQueueStillReservesDispatchLease(): void
115 + public function testShutdownRepairsDatabaseBeforeUsingQueueApis(): void
104 116 {
117 + $GLOBALS['sync_basalam_jobs_runner_test_state']['current_filter'] = 'shutdown';
118 + $GLOBALS['wpdb'] = new FakeWpdb();
119 +
105 120 $jobManager = new FakeJobManager([false]);
106 121 $runner = $this->newRunner($jobManager);
107 122
108 123 $runner->maybeDispatchAsyncRequest();
109 124
110 - self::assertSame(['get_transient', 'set_transient', 'has_pending_jobs'], $this->state()['events']);
125 + self::assertSame(
126 + [
127 + 'fastcgi_finish_request',
128 + 'db_flush',
129 + 'db_check_connection',
130 + 'get_transient',
131 + 'get_transient',
132 + 'has_pending_jobs',
133 + 'set_transient',
134 + ],
135 + $this->state()['events']
136 + );
137 + self::assertSame([false], $GLOBALS['wpdb']->allowBailValues);
138 + }
139 +
140 + public function testEmptyQueueReservesOnlyShortIdleProbeLease(): void
141 + {
142 + $jobManager = new FakeJobManager([false]);
143 + $runner = $this->newRunner($jobManager);
144 +
145 + $runner->maybeDispatchAsyncRequest();
146 +
147 + self::assertSame(['get_transient', 'get_transient', 'has_pending_jobs', 'set_transient'], $this->state()['events']);
111 148 self::assertSame([120], $jobManager->timeouts);
112 149 self::assertSame(
113 150 [[
114 - 'name' => self::DISPATCH_LOCK,
151 + 'name' => self::IDLE_PROBE_LOCK,
115 152 'value' => 1,
116 - 'expiration' => 25,
153 + 'expiration' => 5,
117 154 ]],
118 155 $this->state()['transient_writes']
119 156 );
120 157 self::assertSame([], $this->state()['remote_requests']);
@@ -119,23 +156,22 @@
119 156 );
120 157 self::assertSame([], $this->state()['remote_requests']);
121 158 }
122 159
123 - public function testEmptyQueueLeasePreventsASecondProbeInTheSameRequest(): void
160 + public function testNewJobBypassesIdleProbeLeaseAndDispatchesImmediately(): void
124 161 {
125 162 $jobManager = new FakeJobManager([false, true]);
126 163 $runner = $this->newRunner($jobManager);
127 164
128 - // The shutdown probe reserves the lease even when no work is found.
129 165 $runner->maybeDispatchAsyncRequest();
130 166 self::assertCount(1, $this->state()['transient_writes']);
131 167
132 - // A second callback in the same request must observe that lease.
168 + $GLOBALS['sync_basalam_jobs_runner_test_state']['current_filter'] = 'sync_basalam_job_created';
133 169 $runner->maybeDispatchAsyncRequest();
134 170
135 - self::assertSame([120], $jobManager->timeouts);
136 - self::assertCount(1, $this->state()['transient_writes']);
137 - self::assertCount(0, $this->state()['remote_requests']);
171 + self::assertSame([120, 120], $jobManager->timeouts);
172 + self::assertSame(self::DISPATCH_LOCK, $this->state()['transient_writes'][1]['name']);
173 + self::assertCount(1, $this->state()['remote_requests']);
138 174 }
139 175
140 176 public function testExistingLockSkipsQueueCheckAndDispatch(): void
141 177 {
@@ -144,9 +180,9 @@
144 180 $runner = $this->newRunner($jobManager);
145 181
146 182 $runner->maybeDispatchAsyncRequest();
147 183
148 - self::assertSame(['get_transient'], $this->state()['events']);
184 + self::assertSame(['get_transient', 'get_transient'], $this->state()['events']);
149 185 self::assertSame([], $jobManager->timeouts);
150 186 self::assertSame([], $this->state()['transient_writes']);
151 187 self::assertSame([], $this->state()['remote_requests']);
152 188 }
@@ -253,8 +289,26 @@
253 289 $GLOBALS['sync_basalam_jobs_runner_test_state']['events'][] = 'has_pending_jobs';
254 290 $this->timeouts[] = $timeout;
255 291
256 292 return (bool) array_shift($this->pendingResults);
293 + }
294 +}
295 +
296 +class FakeWpdb
297 +{
298 + public $allowBailValues = [];
299 +
300 + public function flush(): void
301 + {
302 + $GLOBALS['sync_basalam_jobs_runner_test_state']['events'][] = 'db_flush';
303 + }
304 +
305 + public function check_connection($allowBail = true): bool
306 + {
307 + $GLOBALS['sync_basalam_jobs_runner_test_state']['events'][] = 'db_check_connection';
308 + $this->allowBailValues[] = $allowBail;
309 +
310 + return true;
257 311 }
258 312 }
259 313
260 314 class FakeHttpBlockService