Skip to content

Commit

Permalink
Merge pull request #13 from Vectorial1024/serial
Browse files Browse the repository at this point in the history
Use opis/closure 4.0
  • Loading branch information
Vectorial1024 authored Jan 26, 2025
2 parents c89946f + 9fb937d commit b52d232
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
7 changes: 5 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -50,5 +50,8 @@
"Vectorial1024\\LaravelProcessAsync\\ProcessAsyncServiceProvider"
]
}
},
"config": {
"sort-packages": true
}
}
35 changes: 24 additions & 11 deletions src/AsyncTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@
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.
*/
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).
Expand Down Expand Up @@ -105,17 +106,31 @@ 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.");
}
$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.
*
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit b52d232

Please sign in to comment.