From 9d8aa9226eb8d84cb55584a84ea4712882fb4e5a Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Fri, 3 Jan 2025 17:42:02 +0800 Subject: [PATCH 1/8] Install opis/closure --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b75b7e4..aeb2472 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,8 @@ "php": "^8.1", "illuminate/support": "^10.0|^11.0", "laravel/serializable-closure": "^1.0", - "loophp/phposinfo": "^1.8" + "loophp/phposinfo": "^1.8", + "opis/closure": "^4.0" }, "require-dev": { "phpunit/phpunit": "^10", From 791d6f49699b4d4f74f70163489e9aaa8ebb5969 Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Fri, 3 Jan 2025 18:46:11 +0800 Subject: [PATCH 2/8] Try using new closure library --- src/AsyncTask.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/AsyncTask.php b/src/AsyncTask.php index a0ed917..e252398 100644 --- a/src/AsyncTask.php +++ b/src/AsyncTask.php @@ -7,11 +7,12 @@ use Closure; use Illuminate\Process\InvokedProcess; use Illuminate\Support\Facades\Process; -use Laravel\SerializableClosure\SerializableClosure; use LogicException; use loophp\phposinfo\OsInfo; use RuntimeException; +use function Opis\Closure\{serialize, unserialize}; + /** * The common handler of an AsyncTask; this can be a closure (will be wrapped inside AsyncTask) or an interface instance. */ @@ -19,9 +20,9 @@ class AsyncTask { /** * The task to be executed in the background. - * @var SerializableClosure|AsyncTaskInterface + * @var Closure|AsyncTaskInterface */ - private SerializableClosure|AsyncTaskInterface $theTask; + private Closure|AsyncTaskInterface $theTask; /** * The process that is actually running this task. Tasks that are not started will have null here. @@ -94,10 +95,7 @@ class AsyncTask */ public function __construct(Closure|AsyncTaskInterface $theTask) { - if ($theTask instanceof Closure) { - // convert to serializable closure first - $theTask = new SerializableClosure($theTask); - } + // opis/closure allows direct storage of closure $this->theTask = $theTask; } @@ -142,10 +140,8 @@ public function run(): void } // then, execute the task itself - if ($this->theTask instanceof SerializableClosure) { - $innerClosure = $this->theTask->getClosure(); - $innerClosure(); - unset($innerClosure); + if ($this->theTask instanceof Closure) { + ($this->theTask)(); } else { // must be AsyncTaskInterface $this->theTask->execute(); From 00634ee7443f5db5145acb7e2162ce93761f9f23 Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Sat, 4 Jan 2025 12:25:07 +0800 Subject: [PATCH 3/8] Serialize only the necessary info --- src/AsyncTask.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/AsyncTask.php b/src/AsyncTask.php index e252398..59c8f5f 100644 --- a/src/AsyncTask.php +++ b/src/AsyncTask.php @@ -99,6 +99,24 @@ public function __construct(Closure|AsyncTaskInterface $theTask) $this->theTask = $theTask; } + public function __serialize(): array + { + // serialize only the necessary info to reduce runner cmd length + return [ + 'theTask' => serialize($this->theTask), + 'timeLimit' => $this->timeLimit, + ]; + } + + public function __unserialize($data): void + { + [ + 'theTask' => $tempTask, + 'timeLimit' => $this->timeLimit, + ] = $data; + $this->theTask = unserialize($tempTask); + } + /** * Inside an available PHP process, runs this AsyncTask instance. * From 32531577bbf66175921ba553f383fdc8e8d53ae5 Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Sat, 4 Jan 2025 15:55:10 +0800 Subject: [PATCH 4/8] Skip 1 level of serialization --- src/AsyncTask.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AsyncTask.php b/src/AsyncTask.php index 59c8f5f..79851fc 100644 --- a/src/AsyncTask.php +++ b/src/AsyncTask.php @@ -103,7 +103,7 @@ public function __serialize(): array { // serialize only the necessary info to reduce runner cmd length return [ - 'theTask' => serialize($this->theTask), + 'theTask' => $this->theTask, 'timeLimit' => $this->timeLimit, ]; } @@ -111,10 +111,10 @@ public function __serialize(): array public function __unserialize($data): void { [ - 'theTask' => $tempTask, + 'theTask' => $this->theTask, 'timeLimit' => $this->timeLimit, ] = $data; - $this->theTask = unserialize($tempTask); + // $this->theTask = unserialize($tempTask); } /** From ae22e6f732c2e6b6a4c837080ae99f3b3035d632 Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Sun, 26 Jan 2025 19:07:34 +0800 Subject: [PATCH 5/8] Adjust serializable-closure version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2649093..7ca0106 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "require": { "php": "^8.1", "illuminate/support": "^10.0|^11.0", - "laravel/serializable-closure": "^1.0", + "laravel/serializable-closure": "^2.0", "loophp/phposinfo": "^1.8", "opis/closure": "^4.0" }, From a2da0e5019c338c27f0c8db0d4a7df08250601c3 Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Sun, 26 Jan 2025 19:12:01 +0800 Subject: [PATCH 6/8] Adjust package requirements --- README.md | 2 +- composer.json | 4 +++- src/AsyncTask.php | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 60be4a9..8a5aa69 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Utilize Laravel Processes to run PHP code asynchronously, as if using Laravel Co ## What really is this? [Laravel Processes](https://laravel.com/docs/10.x/processes) was first introduced in Laravel 10. This library wraps around `Process::start()` to let you execute code in the background to achieve async, albeit with some caveats: - You may only execute PHP code -- Restrictions from `laravel/serializable-closure` apply (see [their README](https://github.com/laravel/serializable-closure)) +- Restrictions from `opis/closure` apply (see [their README](https://github.com/opis/closure)) - Hands-off execution: no built-in result-checking, check the results yourself (e.g. via database, file cache, etc) This library internally uses an Artisan command to run the async code, which is similar to Laravel 11 [Concurrency](https://laravel.com/docs/11.x/concurrency). diff --git a/composer.json b/composer.json index 7ca0106..36f891e 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,6 @@ "require": { "php": "^8.1", "illuminate/support": "^10.0|^11.0", - "laravel/serializable-closure": "^2.0", "loophp/phposinfo": "^1.8", "opis/closure": "^4.0" }, @@ -51,5 +50,8 @@ "Vectorial1024\\LaravelProcessAsync\\ProcessAsyncServiceProvider" ] } + }, + "config": { + "sort-packages": true } } diff --git a/src/AsyncTask.php b/src/AsyncTask.php index 44a33b3..8a14879 100644 --- a/src/AsyncTask.php +++ b/src/AsyncTask.php @@ -9,7 +9,6 @@ use Illuminate\Support\Facades\Process; use Illuminate\Support\Str; use InvalidArgumentException; -use Laravel\SerializableClosure\SerializableClosure; use LogicException; use loophp\phposinfo\OsInfo; use RuntimeException; From c02640de6736497bdca139646a3780c419e10964 Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Sun, 26 Jan 2025 19:18:34 +0800 Subject: [PATCH 7/8] Clean up the comment --- src/AsyncTask.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/AsyncTask.php b/src/AsyncTask.php index 8a14879..4b24ee5 100644 --- a/src/AsyncTask.php +++ b/src/AsyncTask.php @@ -129,7 +129,6 @@ public function __unserialize($data): void 'theTask' => $this->theTask, 'timeLimit' => $this->timeLimit, ] = $data; - // $this->theTask = unserialize($tempTask); } /** From 9fb937d3e9ab0bca5deb3b45515b7cf3aec1d660 Mon Sep 17 00:00:00 2001 From: Vincent Wong Date: Sun, 26 Jan 2025 19:28:09 +0800 Subject: [PATCH 8/8] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc94ec1..7f39e83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Note: you may refer to `README.md` for description of features. ## Dev (WIP) - Task IDs can be given to tasks (generated or not) (https://github.com/Vectorial1024/laravel-process-async/issues/5) +- Updated to use `opis/closure` 4.0 for task details serialization (https://github.com/Vectorial1024/laravel-process-async/issues/12) + - Technically a breaking internal change, but no code change expected and downtime is expected to be almost negligible ## 0.2.0 (2025-01-04) - Task runners are now detached from the task giver (https://github.com/Vectorial1024/laravel-process-async/issues/7)