From 73ba518c502503abeba966673c41282018f4b3bc Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Mon, 1 Dec 2025 08:49:51 +0100 Subject: [PATCH 1/2] PHP 8.4/8.5: Upgrade library `react/promise` Current latest version is `3.3.0` - PHP 8.4 support was introduced in v3.2.0 (https://github.com/reactphp/promise/blob/3.x/CHANGELOG.md#320-2024-05-24). - PHP 8.5 support was inteoduced in v3.3.0 (https://github.com/reactphp/promise/releases/tag/v3.3.0) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 984c5b6..1f7603d 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "psr/log": "^1", "ramsey/uuid": "^4.2.3", "react/event-loop": "^1.4", - "react/promise": "^2.10", + "react/promise": "^3.3", "simshaun/recurr": "^5", "ipl/stdlib": ">=0.12.0" }, From 6e2f91e901d637efb516c97afeab9f2bd9a73476 Mon Sep 17 00:00:00 2001 From: Sukhwinder Dhillon Date: Mon, 1 Dec 2025 16:35:23 +0100 Subject: [PATCH 2/2] Replace deprecated methods and interfaces of `react/promise` - method resolve() requires a param - method always() is deprecated, use finally() instead - (Extended|Cancellable)PromiseInterface are removed since v3.0.0 ref https://reactphp.org/promise/changelog.html#300-2023-07-11 --- src/Common/Promises.php | 2 +- src/Contract/Task.php | 6 +++--- src/Scheduler.php | 19 +++++++++---------- tests/Lib/PromiseBoundTask.php | 8 ++++---- tests/SchedulerTest.php | 28 ++++++++++++++-------------- 5 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/Common/Promises.php b/src/Common/Promises.php index 2b93290..fed8a68 100644 --- a/src/Common/Promises.php +++ b/src/Common/Promises.php @@ -45,7 +45,7 @@ protected function addPromise(UuidInterface $uuid, PromiseInterface $promise): s * **Example Usage:** * * ```php - * $promise->always(function () use ($uuid, $promise) { + * $promise->finally(function () use ($uuid, $promise) { * $promises->removePromise($uuid, $promise); * }) * ``` diff --git a/src/Contract/Task.php b/src/Contract/Task.php index db09ddc..22604e6 100644 --- a/src/Contract/Task.php +++ b/src/Contract/Task.php @@ -3,7 +3,7 @@ namespace ipl\Scheduler\Contract; use Ramsey\Uuid\UuidInterface; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; interface Task { @@ -33,7 +33,7 @@ public function getDescription(): ?string; * * This commits the actions in a non-blocking fashion to the event loop and yields a deferred promise * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function run(): ExtendedPromiseInterface; + public function run(): PromiseInterface; } diff --git a/src/Scheduler.php b/src/Scheduler.php index d32d25e..fc2f186 100644 --- a/src/Scheduler.php +++ b/src/Scheduler.php @@ -11,7 +11,7 @@ use ipl\Stdlib\Events; use React\EventLoop\Loop; use React\Promise; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; use SplObjectStorage; use Throwable; @@ -24,7 +24,7 @@ class Scheduler /** * Event raised when a {@link Task task} is canceled * - * The task and its pending operations as an array of canceled {@link ExtendedPromiseInterface promise}s + * The task and its pending operations as an array of canceled {@link PromiseInterface promise}s * are passed as parameters to the event callbacks. * * **Example usage:** @@ -94,13 +94,13 @@ class Scheduler /** * Event raised upon operation of a {@link Task task} * - * The task and the possibly not yet completed result of the operation as a {@link ExtendedPromiseInterface promise} + * The task and the possibly not yet completed result of the operation as a {@link PromiseInterface promise} * are passed as parameters to the event callbacks. * * **Example usage:** * * ```php - * $scheduler->on($scheduler::ON_TASK_OPERATION, function (Task $task, ExtendedPromiseInterface $_) use ($logger) { + * $scheduler->on($scheduler::ON_TASK_OPERATION, function (Task $task, PromiseInterface $_) use ($logger) { * $logger->info(sprintf('Task %s operating', $task->getName())); * }); * ``` @@ -235,7 +235,7 @@ public function schedule(Task $task, Frequency $frequency): self if ($this->promises->offsetExists($task->getUuid())) { $pendingPromises = (array) $this->promises->offsetGet($task->getUuid()); - Promise\all($pendingPromises)->always($removeTask); + Promise\all($pendingPromises)->finally($removeTask); } else { $removeTask(); } @@ -285,10 +285,9 @@ protected function cancelTask(Task $task): void { Loop::cancelTimer($this->detachTimer($task->getUuid())); - /** @var ExtendedPromiseInterface[] $promises */ + /** @var PromiseInterface[] $promises */ $promises = $this->detachPromises($task->getUuid()); if (! empty($promises)) { - /** @var Promise\CancellablePromiseInterface $promise */ foreach ($promises as $promise) { $promise->cancel(); } @@ -301,9 +300,9 @@ protected function cancelTask(Task $task): void * * @param Task $task * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - protected function runTask(Task $task): ExtendedPromiseInterface + protected function runTask(Task $task): PromiseInterface { $promise = $task->run(); $this->addPromise($task->getUuid(), $promise); @@ -315,7 +314,7 @@ function ($result) use ($task): void { function (Throwable $reason) use ($task): void { $this->emit(self::ON_TASK_FAILED, [$task, $reason]); } - )->always(function () use ($task, $promise): void { + )->finally(function () use ($task, $promise): void { // Unregister the promise without canceling it as it's already resolved $this->removePromise($task->getUuid(), $promise); }); diff --git a/tests/Lib/PromiseBoundTask.php b/tests/Lib/PromiseBoundTask.php index 4e6a68d..d724e35 100644 --- a/tests/Lib/PromiseBoundTask.php +++ b/tests/Lib/PromiseBoundTask.php @@ -5,19 +5,19 @@ use ipl\Scheduler\Common\TaskProperties; use ipl\Scheduler\Contract\Task; use Ramsey\Uuid\Uuid; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; class PromiseBoundTask implements Task { use TaskProperties; - /** @var ExtendedPromiseInterface */ + /** @var PromiseInterface */ protected $promise; /** @var int */ protected $startedPromises = 0; - public function __construct(ExtendedPromiseInterface $promise) + public function __construct(PromiseInterface $promise) { $this->promise = $promise; @@ -31,7 +31,7 @@ public function getStartedPromises(): int return $this->startedPromises; } - public function run(): ExtendedPromiseInterface + public function run(): PromiseInterface { $this->startedPromises++; diff --git a/tests/SchedulerTest.php b/tests/SchedulerTest.php index f58bd1d..0c3a220 100644 --- a/tests/SchedulerTest.php +++ b/tests/SchedulerTest.php @@ -14,7 +14,7 @@ use PHPUnit\Framework\TestCase; use React\EventLoop\Loop; use React\Promise; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; use Throwable; class SchedulerTest extends TestCase @@ -38,7 +38,7 @@ protected function runAndStopEventLoop() public function testSchedulingTasksNotYetDue() { - $task = new PromiseBoundTask(Promise\resolve()); + $task = new PromiseBoundTask(Promise\resolve(null)); $nextDue = new DateTime('+1 week'); $scheduledAt = null; @@ -60,12 +60,12 @@ public function testSchedulingTasksNotYetDue() public function testDoesNotScheduleNeverDueTasks() { $neverRun = true; - $task = new PromiseBoundTask(Promise\resolve()); + $task = new PromiseBoundTask(Promise\resolve(null)); $this->scheduler ->schedule($task, new NeverDueFrequency()) ->on( CountableScheduler::ON_TASK_RUN, - function (Task $_, ExtendedPromiseInterface $p) use (&$neverRun): void { + function (Task $_, PromiseInterface $p) use (&$neverRun): void { $neverRun = false; } ); @@ -82,12 +82,12 @@ function (Task $_, ExtendedPromiseInterface $p) use (&$neverRun): void { public function testDueTasksRunImmediately() { $hasRun = false; - $task = new PromiseBoundTask(Promise\resolve()); + $task = new PromiseBoundTask(Promise\resolve(null)); $this->scheduler ->schedule($task, new ImmediateDueFrequency()) ->on( CountableScheduler::ON_TASK_RUN, - function (Task $t, ExtendedPromiseInterface $_) use (&$hasRun): void { + function (Task $t, PromiseInterface $_) use (&$hasRun): void { $hasRun = true; } ); @@ -174,7 +174,7 @@ public function testFailedTasksPropagateReason() ->schedule($task, new ImmediateDueFrequency()) ->on( CountableScheduler::ON_TASK_RUN, - function (Task $_, ExtendedPromiseInterface $p) use ($deferred): void { + function (Task $_, PromiseInterface $p) use ($deferred): void { $deferred->reject(new TaskRejectedException('rejected')); } ) @@ -208,7 +208,7 @@ public function testDoneTasksPropagateReturn() ->schedule($task, new ImmediateDueFrequency()) ->on( CountableScheduler::ON_TASK_RUN, - function (Task $_, ExtendedPromiseInterface $p) use ($deferred): void { + function (Task $_, PromiseInterface $p) use ($deferred): void { $deferred->resolve(10); } ) @@ -232,8 +232,8 @@ function (Task $_, $result) use (&$taskFulFilled, &$returnResult): void { public function testCountsWithMultipleScheduledTasks() { - $task1 = new PromiseBoundTask(Promise\resolve()); - $task2 = new PromiseBoundTask(Promise\resolve()); + $task1 = new PromiseBoundTask(Promise\resolve(null)); + $task2 = new PromiseBoundTask(Promise\resolve(null)); $task3 = new PromiseBoundTask((new Promise\Deferred())->promise()); $this->scheduler @@ -255,7 +255,7 @@ public function testCountsWithMultipleScheduledTasks() public function testDoesNotScheduleExpiredTasks() { - $task = new PromiseBoundTask(Promise\resolve()); + $task = new PromiseBoundTask(Promise\resolve(null)); $frequency = new ExpiringFrequency(); $frequency->setExpired(); @@ -284,7 +284,7 @@ public function testTaskIsDetachedAfterExpiring() }) ->on( CountableScheduler::ON_TASK_RUN, - function (Task $t, ExtendedPromiseInterface $_) use ($deferred, $frequency): void { + function (Task $t, PromiseInterface $_) use ($deferred, $frequency): void { $frequency->setExpired(); Loop::addTimer(0, function ($timer) use ($deferred): void { @@ -314,10 +314,10 @@ public function testOneOffTasksRunOnlyOnce() ->schedule($task, new OneOff(new DateTime('+1 milliseconds'))) ->on( CountableScheduler::ON_TASK_RUN, - function (Task $t, ExtendedPromiseInterface $_) use (&$countRuns, $deferred): void { + function (Task $t, PromiseInterface $_) use (&$countRuns, $deferred): void { $countRuns += 1; - $deferred->resolve(); + $deferred->resolve(null); } );