Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions .github/workflows/linux-php-8.0.yml

This file was deleted.

15 changes: 0 additions & 15 deletions .github/workflows/linux-php-8.1.yml

This file was deleted.

33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Changelog

All notable changes to **parallel-sdk** are documented in this file. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/).

## `3.0.0` – 2025-07-04

### Added
- **Domain-specific exception hierarchy**
`ActionNotImplementedException`, `InvalidMessageReceivedException`, `NoWorkerDefinedException`, `TaskExecutionFailedException`, `WorkerAlreadyDefinedException`, `WorkerNotDefinedException`, plus a `ParallelException` value object to serialise task-side errors.
- `Scheduler::runTask()` now surfaces worker exceptions through `TaskExecutionFailedException` for clearer diagnostics.
- Adopted modern PHP 8.2 language features:
* `readonly` properties and promoted constructor parameters
* Precise return-type hints (e.g. `void` on closures)
* `match`-style strict comparisons and assorted PSR-12 tidy-ups.

### Changed
- **BC-BREAK:** Minimum supported PHP version raised from 8.0 → **8.2**.
Consumers on <8.2 will remain on the `2.x` series.
- `Scheduler::using()` now throws `WorkerAlreadyDefinedException` when attempting to re-register an existing worker with constructor args.
- Error bubbling in `Scheduler::runTask()` changed from `RuntimeException` with string message to the typed `TaskExecutionFailedException`.

### Removed
- CI workflows for PHP 8.0 & 8.1 ‒ the suite now runs on 8.2/8.3/8.4.
- Legacy catch-all `RuntimeException` branches replaced with specific domain exceptions.

### Fixed
- Sporadic race-condition when starting the runner under PHP ≥ 8.1 by ensuring a micro-sleep and event handshake.
- Several docblock inaccuracies and progress-bar initialisation edge cases.

---

## [2.1.4] – 2024-xx-xx
_Refer to Git history for details prior to the 3.x line._
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ An implementation of [krakjoe/parallel](https://github.com/krakjoe/parallel) PHP
[![Monthly Downloads](https://img.shields.io/packagist/dm/hds-solutions/parallel-sdk?style=flat-square&color=747474&label)](https://packagist.org/packages/hds-solutions/parallel-sdk)
[![Required PHP version](https://img.shields.io/packagist/dependency-v/hds-solutions/parallel-sdk/php?style=flat-square&color=006496&logo=php&logoColor=white)](https://packagist.org/packages/hds-solutions/parallel-sdk)

[![PHP 8.0](https://img.shields.io/github/actions/workflow/status/hds-solutions/parallel-sdk/linux-php-8.0.yml?style=flat-square&logo=github&label=PHP%208.0)](https://github.com/hschimpf/parallel-sdk/actions/workflows/linux-php-8.0.yml)
[![PHP 8.1](https://img.shields.io/github/actions/workflow/status/hds-solutions/parallel-sdk/linux-php-8.1.yml?style=flat-square&logo=github&label=PHP%208.1)](https://github.com/hschimpf/parallel-sdk/actions/workflows/linux-php-8.1.yml)
[![PHP 8.2](https://img.shields.io/github/actions/workflow/status/hds-solutions/parallel-sdk/linux-php-8.2.yml?style=flat-square&logo=github&label=PHP%208.2)](https://github.com/hschimpf/parallel-sdk/actions/workflows/linux-php-8.2.yml)
[![PHP 8.3](https://img.shields.io/github/actions/workflow/status/hds-solutions/parallel-sdk/linux-php-8.3.yml?style=flat-square&logo=github&label=PHP%208.3)](https://github.com/hschimpf/parallel-sdk/actions/workflows/linux-php-8.3.yml)
[![PHP 8.4](https://img.shields.io/github/actions/workflow/status/hds-solutions/parallel-sdk/linux-php-8.4.yml?style=flat-square&logo=github&label=PHP%208.4)](https://github.com/hschimpf/parallel-sdk/actions/workflows/linux-php-8.4.yml)
Expand All @@ -19,7 +17,7 @@ That allow that your code can be deployed in any environment, and if `parallel`
## Installation
### Dependencies
You need these dependencies to execute tasks in parallel.
- PHP >= 8.0 with ZTS enabled
- PHP >= 8.2 with ZTS enabled
- parallel PECL extension _(v1.2.5 or higher)_

Parallel extension documentation can be found on https://php.net/parallel.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"symfony/console": "Allows usage of a shared ProgressBar between the Workers"
},
"require": {
"php": "^8.0"
"php": "^8.2"
},
"autoload": {
"files": [
Expand Down
13 changes: 13 additions & 0 deletions src/Exceptions/ActionNotImplementedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);

namespace HDSSolutions\Console\Parallel\Exceptions;

use RuntimeException;

final class ActionNotImplementedException extends RuntimeException {

public function __construct(string $action) {
parent::__construct(sprintf('Action "%s" not yet implemented', $action));
}

}
13 changes: 13 additions & 0 deletions src/Exceptions/InvalidMessageReceivedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);

namespace HDSSolutions\Console\Parallel\Exceptions;

use RuntimeException;

final class InvalidMessageReceivedException extends RuntimeException {

public function __construct() {
parent::__construct('Invalid message received!');
}

}
13 changes: 13 additions & 0 deletions src/Exceptions/NoWorkerDefinedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);

namespace HDSSolutions\Console\Parallel\Exceptions;

use RuntimeException;

final class NoWorkerDefinedException extends RuntimeException {

public function __construct() {
parent::__construct('No worker is defined');
}

}
2 changes: 1 addition & 1 deletion src/Exceptions/ParallelException.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Throwable;

final class ParallelException {
final readonly class ParallelException {

private string $message;

Expand Down
13 changes: 13 additions & 0 deletions src/Exceptions/TaskExecutionFailedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);

namespace HDSSolutions\Console\Parallel\Exceptions;

use RuntimeException;

final class TaskExecutionFailedException extends RuntimeException {

public function __construct(ParallelException $exception) {
parent::__construct($exception->getMessage());
}

}
15 changes: 15 additions & 0 deletions src/Exceptions/WorkerAlreadyDefinedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types=1);

namespace HDSSolutions\Console\Parallel\Exceptions;

use RuntimeException;

final class WorkerAlreadyDefinedException extends RuntimeException {

public function __construct(string $worker, bool $with_parameters = false) {
parent::__construct(sprintf('Worker class "%s" is already defined%s', $worker,
$with_parameters ? ', you can\'t specify new constructor parameters!' : '',
));
}

}
13 changes: 13 additions & 0 deletions src/Exceptions/WorkerNotDefinedException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);

namespace HDSSolutions\Console\Parallel\Exceptions;

use RuntimeException;

final class WorkerNotDefinedException extends RuntimeException {

public function __construct() {
parent::__construct('Worker is not defined');
}

}
16 changes: 3 additions & 13 deletions src/Internals/Commands/ParallelCommandMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,15 @@

namespace HDSSolutions\Console\Parallel\Internals\Commands;

use RuntimeException;

abstract class ParallelCommandMessage {
abstract readonly class ParallelCommandMessage {

/**
* @param string $action Action to execute
* @param array $args Arguments to pass to the action
*/
public function __construct(
private string $action,
private array $args = [],
public string $action,
public array $args = [],
) {}

public function __get(string $name) {
if ( !property_exists($this, $name)) {
throw new RuntimeException(sprintf('Invalid property "%s"', $name));
}

return $this->$name;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::enableProgressBar()} action
*/
final class EnableProgressBarMessage extends ParallelCommandMessage {
final readonly class EnableProgressBarMessage extends ParallelCommandMessage {

/**
* @param string $identifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* Message sent to {@see ProgressBarWorker} to execute {@see ProgressBarWorker::progressBarAction()}
*/
final class ProgressBarActionMessage extends ParallelCommandMessage {
final readonly class ProgressBarActionMessage extends ParallelCommandMessage {

/**
* @param string $action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see ProgressBarWorker} to execute {@see ProgressBarWorker::registerWorker()} action
*/
final class ProgressBarRegistrationMessage extends ParallelCommandMessage {
final readonly class ProgressBarRegistrationMessage extends ParallelCommandMessage {

/**
* @param string $worker
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/ProgressBar/StatsReportMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* Message sent to {@see ProgressBarWorker} to execute {@see ProgressBarWorker::statsReport()}
*/
final class StatsReportMessage extends ParallelCommandMessage {
final readonly class StatsReportMessage extends ParallelCommandMessage {

/**
* @param string $worker_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::getRegisteredWorker()} action
*/
final class GetRegisteredWorkerMessage extends ParallelCommandMessage {
final readonly class GetRegisteredWorkerMessage extends ParallelCommandMessage {

/**
* @param string $worker
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/GetTasksMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::getTasks()} action
*/
final class GetTasksMessage extends ParallelCommandMessage {
final readonly class GetTasksMessage extends ParallelCommandMessage {

public function __construct() {
parent::__construct('get_tasks');
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/QueueTaskMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::queueTask()} action
*/
final class QueueTaskMessage extends ParallelCommandMessage {
final readonly class QueueTaskMessage extends ParallelCommandMessage {

/**
* @param array $data
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/RegisterWorkerMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::registerWorker()} action
*/
final class RegisterWorkerMessage extends ParallelCommandMessage {
final readonly class RegisterWorkerMessage extends ParallelCommandMessage {

/**
* @param string|Closure $worker
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/RemoveAllTasksMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::removeAllTasks()} action
*/
final class RemoveAllTasksMessage extends ParallelCommandMessage {
final readonly class RemoveAllTasksMessage extends ParallelCommandMessage {

public function __construct() {
parent::__construct('remove_all_tasks');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::removePendingTasks()} action
*/
final class RemovePendingTasksMessage extends ParallelCommandMessage {
final readonly class RemovePendingTasksMessage extends ParallelCommandMessage {

public function __construct() {
parent::__construct('remove_pending_tasks');
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/RemoveTaskMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::removeTask()} action
*/
final class RemoveTaskMessage extends ParallelCommandMessage {
final readonly class RemoveTaskMessage extends ParallelCommandMessage {

/**
* @param int $task_id
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/SetMaxCpuUsage.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::setMaxCpuCountUsage()} | {@see Runner::setMaxCpuPercentageUsage()} action
*/
final class SetMaxCpuUsage extends ParallelCommandMessage {
final readonly class SetMaxCpuUsage extends ParallelCommandMessage {

public function __construct(int | float $max, bool $percentage = false) {
parent::__construct(sprintf('set_max_cpu_%s_usage', $percentage ? 'percentage' : 'count'), [ $max ]);
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/StopRunningTasksMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::stopRunningTasks()} action
*/
final class StopRunningTasksMessage extends ParallelCommandMessage {
final readonly class StopRunningTasksMessage extends ParallelCommandMessage {

public function __construct() {
parent::__construct('stop_running_tasks', [ true ]);
Expand Down
2 changes: 1 addition & 1 deletion src/Internals/Commands/Runner/UpdateMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::update()} action
*/
final class UpdateMessage extends ParallelCommandMessage {
final readonly class UpdateMessage extends ParallelCommandMessage {

public function __construct() {
parent::__construct('update');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/**
* Message sent to {@see Runner} to execute {@see Runner::await()} action
*/
final class WaitTasksCompletionMessage extends ParallelCommandMessage {
final readonly class WaitTasksCompletionMessage extends ParallelCommandMessage {

/**
* @param DateInterval|null $wait_until
Expand Down
11 changes: 6 additions & 5 deletions src/Internals/Common/ListenEventsAndExecuteActions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

namespace HDSSolutions\Console\Parallel\Internals\Common;

use HDSSolutions\Console\Parallel\Exceptions\ActionNotImplementedException;
use HDSSolutions\Console\Parallel\Exceptions\InvalidMessageReceivedException;
use HDSSolutions\Console\Parallel\Exceptions\ParallelException;
use HDSSolutions\Console\Parallel\Internals\Commands\ParallelCommandMessage;
use RuntimeException;
use parallel\Channel;
use parallel\Events\Event;
use Throwable;

trait ListenEventsAndExecuteActions {

/**
* Watch for events. This is used only on a multi-threaded environment
* Watch for events. This is used only on a multithreaded environment
*/
final public function listen(): void {
// notify successful start
Expand All @@ -23,7 +24,7 @@ final public function listen(): void {
try {
// check if we got a valid message
if ( !($message instanceof ParallelCommandMessage)) {
throw new RuntimeException('Invalid message received!');
throw new InvalidMessageReceivedException;
}

// process message
Expand All @@ -45,12 +46,12 @@ abstract protected function afterListening(): void;
* @param ParallelCommandMessage $message
*
* @return mixed
* @throws RuntimeException If the requested action isn't implemented
* @throws ActionNotImplementedException If the requested action isn't implemented
*/
final public function processMessage(ParallelCommandMessage $message): mixed {
// check if action is implemented
if ( !method_exists($this, $method = lcfirst(implode('', array_map('ucfirst', explode('_', $message->action)))))) {
throw new RuntimeException(sprintf('Action "%s" not yet implemented', $message->action));
throw new ActionNotImplementedException($message->action);
}

// execute action and return the result
Expand Down
Loading