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) 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 86a3853..36f891e 100644 --- a/composer.json +++ b/composer.json @@ -33,8 +33,8 @@ "require": { "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", @@ -50,5 +50,8 @@ "Vectorial1024\\LaravelProcessAsync\\ProcessAsyncServiceProvider" ] } + }, + "config": { + "sort-packages": true } } diff --git a/src/AsyncTask.php b/src/AsyncTask.php index 37c30fd..4b24ee5 100644 --- a/src/AsyncTask.php +++ b/src/AsyncTask.php @@ -9,11 +9,12 @@ use Illuminate\Support\Facades\Process; use Illuminate\Support\Str; use InvalidArgumentException; -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. */ @@ -21,9 +22,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 user-specified ID of the current task. (Null means user did not specify any ID). @@ -105,10 +106,7 @@ class AsyncTask */ public function __construct(Closure|AsyncTaskInterface $theTask, string|null $taskID = null) { - if ($theTask instanceof Closure) { - // convert to serializable closure first - $theTask = new SerializableClosure($theTask); - } + // opis/closure allows direct storage of closure $this->theTask = $theTask; if ($taskID === "") { throw new InvalidArgumentException("AsyncTask ID cannot be empty."); @@ -116,6 +114,23 @@ public function __construct(Closure|AsyncTaskInterface $theTask, string|null $ta $this->taskID = $taskID; } + public function __serialize(): array + { + // serialize only the necessary info to reduce runner cmd length + return [ + 'theTask' => $this->theTask, + 'timeLimit' => $this->timeLimit, + ]; + } + + public function __unserialize($data): void + { + [ + 'theTask' => $this->theTask, + 'timeLimit' => $this->timeLimit, + ] = $data; + } + /** * Inside an available PHP process, runs this AsyncTask instance. * @@ -159,10 +174,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();