From ea09a100cd51844eddb303e0dd2bb660b1bb1490 Mon Sep 17 00:00:00 2001 From: Bart Vanhoutte Date: Thu, 15 Dec 2022 16:03:41 +0100 Subject: [PATCH 1/8] Worked on removing usage of dynamic properties. --- src/Queue.php | 35 +++++++++++++++++++++-------------- src/State.php | 11 +++++++++++ 2 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 src/State.php diff --git a/src/Queue.php b/src/Queue.php index f4e827b..4e696db 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -27,6 +27,7 @@ class Queue implements \Countable private $pending = 0; private $queue = array(); + private $state = array(); /** * Concurrently process all given jobs through the given `$handler`. @@ -364,23 +365,27 @@ public function __invoke() end($queue); $id = key($queue); - $deferred = new Deferred(function ($_, $reject) use (&$queue, $id, &$deferred) { + $state = new State(); + $deferred = new Deferred(function ($_, $reject) use (&$queue, $id, &$state) { // forward cancellation to pending operation if it is currently executing - if (isset($deferred->pending) && $deferred->pending instanceof PromiseInterface && \method_exists($deferred->pending, 'cancel')) { - $deferred->pending->cancel(); + if (isset($state->pending) && $state->pending instanceof PromiseInterface && \method_exists($state->pending, 'cancel')) { + $state->pending->cancel(); } - unset($deferred->pending); + unset($state->pending); - if (isset($deferred->args)) { + if (isset($state->args)) { // queued promise cancelled before its handler is invoked // remove from queue and reject explicitly - unset($queue[$id], $deferred->args); + unset($queue[$id], $state->args); $reject(new \RuntimeException('Cancelled queued job before processing started')); } }); + $this->state[spl_object_hash($deferred)] = $state; + // queue job to process if number of pending jobs is below concurrency limit again - $deferred->args = func_get_args(); + + $state->args = func_get_args(); $queue[$id] = $deferred; return $deferred->promise(); @@ -428,18 +433,20 @@ public function processQueue() // await this situation, invoke handler and await its resolution before invoking next queued job ++$this->pending; - $promise = call_user_func_array($this->handler, $deferred->args); - $deferred->pending = $promise; - unset($deferred->args); + $state = $this->state[spl_object_hash($deferred)]; + $promise = call_user_func_array($this->handler, $state->args); + $state->pending = $promise; + unset($state->args); + $that = $this; // invoke handler and await its resolution before invoking next queued job $this->await($promise)->then( - function ($result) use ($deferred) { - unset($deferred->pending); + function ($result) use ($deferred, &$that) { + unset($that->state[spl_object_hash($deferred)]); $deferred->resolve($result); }, - function ($e) use ($deferred) { - unset($deferred->pending); + function ($e) use ($deferred, &$that) { + unset($that->state[spl_object_hash($deferred)]); $deferred->reject($e); } ); diff --git a/src/State.php b/src/State.php new file mode 100644 index 0000000..90e2e4f --- /dev/null +++ b/src/State.php @@ -0,0 +1,11 @@ + Date: Thu, 15 Dec 2022 16:04:00 +0100 Subject: [PATCH 2/8] Added PHP 8.2 to the workflow matrix. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 465821a..e67886d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,7 @@ jobs: strategy: matrix: php: + - 8.2 - 8.1 - 8.0 - 7.4 From 723fb6406138bca3022b4ad334b5d163d39b3db6 Mon Sep 17 00:00:00 2001 From: Bart Vanhoutte Date: Thu, 15 Dec 2022 16:08:07 +0100 Subject: [PATCH 3/8] Removed strict mode for PHP 5.3 compatibility. --- src/State.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/State.php b/src/State.php index 90e2e4f..d585f6b 100644 --- a/src/State.php +++ b/src/State.php @@ -1,7 +1,5 @@ Date: Thu, 15 Dec 2022 16:14:44 +0100 Subject: [PATCH 4/8] Worked on PHP 5.3 compatibility. --- src/Queue.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Queue.php b/src/Queue.php index 4e696db..4c9e24f 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -27,7 +27,9 @@ class Queue implements \Countable private $pending = 0; private $queue = array(); - private $state = array(); + + /** @internal Make this private when support for PHP 5.3 is dropped. */ + public $state = array(); /** * Concurrently process all given jobs through the given `$handler`. From 3097e3000b35f2a31cef3894c29baaa7bf9ce2fa Mon Sep 17 00:00:00 2001 From: Bart Vanhoutte Date: Thu, 15 Dec 2022 16:30:47 +0100 Subject: [PATCH 5/8] Small improvement by only hashing the deferred object once. --- src/Queue.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Queue.php b/src/Queue.php index 4c9e24f..fb9f168 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -435,7 +435,8 @@ public function processQueue() // await this situation, invoke handler and await its resolution before invoking next queued job ++$this->pending; - $state = $this->state[spl_object_hash($deferred)]; + $deferredHash = spl_object_hash($deferred); + $state = $this->state[$deferredHash]; $promise = call_user_func_array($this->handler, $state->args); $state->pending = $promise; unset($state->args); @@ -443,12 +444,12 @@ public function processQueue() $that = $this; // invoke handler and await its resolution before invoking next queued job $this->await($promise)->then( - function ($result) use ($deferred, &$that) { - unset($that->state[spl_object_hash($deferred)]); + function ($result) use ($deferred, &$that, $deferredHash) { + unset($that->state[$deferredHash]); $deferred->resolve($result); }, - function ($e) use ($deferred, &$that) { - unset($that->state[spl_object_hash($deferred)]); + function ($e) use ($deferred, &$that, $deferredHash) { + unset($that->state[$deferredHash]); $deferred->reject($e); } ); From 8ebf0ce78fb701abca2b0caca7a50ecd734da5a3 Mon Sep 17 00:00:00 2001 From: Bart Vanhoutte Date: Thu, 15 Dec 2022 16:03:41 +0100 Subject: [PATCH 6/8] Worked on removing usage of dynamic properties. --- .github/workflows/ci.yml | 1 + src/Queue.php | 38 ++++++++++++++++++++++++-------------- src/State.php | 9 +++++++++ 3 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 src/State.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 465821a..e67886d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,7 @@ jobs: strategy: matrix: php: + - 8.2 - 8.1 - 8.0 - 7.4 diff --git a/src/Queue.php b/src/Queue.php index f4e827b..fb9f168 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -28,6 +28,9 @@ class Queue implements \Countable private $pending = 0; private $queue = array(); + /** @internal Make this private when support for PHP 5.3 is dropped. */ + public $state = array(); + /** * Concurrently process all given jobs through the given `$handler`. * @@ -364,23 +367,27 @@ public function __invoke() end($queue); $id = key($queue); - $deferred = new Deferred(function ($_, $reject) use (&$queue, $id, &$deferred) { + $state = new State(); + $deferred = new Deferred(function ($_, $reject) use (&$queue, $id, &$state) { // forward cancellation to pending operation if it is currently executing - if (isset($deferred->pending) && $deferred->pending instanceof PromiseInterface && \method_exists($deferred->pending, 'cancel')) { - $deferred->pending->cancel(); + if (isset($state->pending) && $state->pending instanceof PromiseInterface && \method_exists($state->pending, 'cancel')) { + $state->pending->cancel(); } - unset($deferred->pending); + unset($state->pending); - if (isset($deferred->args)) { + if (isset($state->args)) { // queued promise cancelled before its handler is invoked // remove from queue and reject explicitly - unset($queue[$id], $deferred->args); + unset($queue[$id], $state->args); $reject(new \RuntimeException('Cancelled queued job before processing started')); } }); + $this->state[spl_object_hash($deferred)] = $state; + // queue job to process if number of pending jobs is below concurrency limit again - $deferred->args = func_get_args(); + + $state->args = func_get_args(); $queue[$id] = $deferred; return $deferred->promise(); @@ -428,18 +435,21 @@ public function processQueue() // await this situation, invoke handler and await its resolution before invoking next queued job ++$this->pending; - $promise = call_user_func_array($this->handler, $deferred->args); - $deferred->pending = $promise; - unset($deferred->args); + $deferredHash = spl_object_hash($deferred); + $state = $this->state[$deferredHash]; + $promise = call_user_func_array($this->handler, $state->args); + $state->pending = $promise; + unset($state->args); + $that = $this; // invoke handler and await its resolution before invoking next queued job $this->await($promise)->then( - function ($result) use ($deferred) { - unset($deferred->pending); + function ($result) use ($deferred, &$that, $deferredHash) { + unset($that->state[$deferredHash]); $deferred->resolve($result); }, - function ($e) use ($deferred) { - unset($deferred->pending); + function ($e) use ($deferred, &$that, $deferredHash) { + unset($that->state[$deferredHash]); $deferred->reject($e); } ); diff --git a/src/State.php b/src/State.php new file mode 100644 index 0000000..d585f6b --- /dev/null +++ b/src/State.php @@ -0,0 +1,9 @@ + Date: Mon, 19 Dec 2022 15:59:02 +0100 Subject: [PATCH 7/8] Whitespace. --- src/State.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/State.php b/src/State.php index d585f6b..c595a0a 100644 --- a/src/State.php +++ b/src/State.php @@ -1,8 +1,10 @@ Date: Mon, 19 Dec 2022 16:00:41 +0100 Subject: [PATCH 8/8] Marked State class as internal. --- src/State.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/State.php b/src/State.php index c595a0a..a7d780e 100644 --- a/src/State.php +++ b/src/State.php @@ -2,6 +2,7 @@ namespace Clue\React\Mq; +/** @internal */ final class State {