diff --git a/README.md b/README.md
index 290d126..6d5036e 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,7 @@ _**Todo:** Tests are working but could cover more._
6. [Dispatcher usage](#dispatcher-usage)
7. [Start workers daemon](#start-workers-daemon)
8. [Usage with Supervisor](#usage-with-supervisor)
+9. [PHP 8.4 Compatibility](#php-8-4-compatibility)
## Requirements
@@ -191,3 +192,22 @@ numprocs=12
autostart=true
autorestart=true
```
+
+
+## PHP 8.4 Compatibility
+
+This library has been updated to support PHP 8.4+ with the following improvements:
+
+- Strong type declarations throughout the codebase
+- Modern property declarations
+- Updated serialization methods
+- Improved error handling
+- Modern dependency versions
+- Strict typing enabled
+- Updated PHPUnit testing suite
+
+To use with PHP 8.4+, ensure you have:
+
+- PHP 8.4 or higher
+- Latest PECL Gearman extension
+- Gearman 1.0+ server
diff --git a/composer.json b/composer.json
index 469698d..6570adb 100644
--- a/composer.json
+++ b/composer.json
@@ -12,14 +12,14 @@
}
],
"require": {
- "php": ">=5.4.0",
+ "php": ">=8.1",
"ext-gearman": "*",
- "psr/log": "~1",
- "react/event-loop": "0.4.*",
- "symfony/console": "2.*|3.4.*|4.1.*|5.*"
+ "psr/log": "^3.0",
+ "react/event-loop": "^1.4",
+ "symfony/console": "^6.0|^7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4"
+ "phpunit/phpunit": "^10.0"
},
"autoload": {
"psr-4": {
diff --git a/src/Application.php b/src/Application.php
index e51dca3..e4bb2e1 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -6,8 +6,7 @@
use GearmanJob;
use Psr\Log\LoggerInterface;
use React\EventLoop\Factory as Loop;
-use React\EventLoop\LibEventLoop;
-use React\EventLoop\StreamSelectLoop;
+use React\EventLoop\LoopInterface;
use Serializable;
use Sinergi\Gearman\Exception\InvalidBootstrapClassException;
@@ -16,75 +15,74 @@ class Application implements Serializable
/**
* @var Config
*/
- private $config;
+ private Config $config;
/**
* @var Process
*/
- private $process;
+ private Process $process;
/**
* @var array
*/
- private $callbacks = [];
+ private array $callbacks = [];
/**
* @var StreamSelectLoop|LibEventLoop
*/
- private $loop;
+ private ?LoopInterface $loop = null;
/**
* @var bool|resource
*/
- private $lock = false;
+ private bool|resource $lock = false;
/**
* @var bool
*/
- private $kill = false;
+ private bool $kill = false;
/**
* @var Worker
*/
- private $worker;
+ private ?Worker $worker = null;
/**
* @var array
*/
- private $jobs = [];
+ private array $jobs = [];
/**
* @var LoggerInterface
*/
- public $logger;
+ public ?LoggerInterface $logger = null;
/**
* @var bool
*/
- public $isAllowingJob = false;
+ public bool $isAllowingJob = false;
/**
* @var bool
*/
- public $isBootstraped = false;
+ public bool $isBootstraped = false;
/**
* @var Application
*/
- private static $instance;
+ private static ?self $instance = null;
/**
* gets the instance via lazy initialization (created on first usage)
*
* @return self
*/
- public static function getInstance()
+ public static function getInstance(): self
{
- if (null === static::$instance) {
- static::$instance = new static;
+ if (self::$instance === null) {
+ self::$instance = new self();
}
-
- return static::$instance;
+ return self::$instance;
}
/**
@@ -93,23 +91,22 @@ public static function getInstance()
* @param Process $process
* @param LoggerInterface|null $logger
*/
- public function __construct(Config $config = null, Process $process = null, $loop = null, LoggerInterface $logger = null)
- {
- static::$instance = $this;
-
- if (null === $config) {
- $config = Config::getInstance();
- }
- $this->setConfig($config);
+ public function __construct(
+ ?Config $config = null,
+ ?Process $process = null,
+ ?LoopInterface $loop = null,
+ ?LoggerInterface $logger = null
+ ) {
+ self::$instance = $this;
- if (null !== $logger) {
- $this->setLogger($logger);
- }
-
- if (null !== $process) {
+ $this->config = $config ?? Config::getInstance();
+ $this->logger = $logger;
+
+ if ($process !== null) {
$this->setProcess($process);
}
- if ($loop instanceof StreamSelectLoop || $loop instanceof LibEventLoop) {
+
+ if ($loop !== null) {
$this->setLoop($loop);
}
}
@@ -340,16 +337,19 @@ private function createLoop($restart = false)
* @param Application $root
* @return mixed
*/
- public function executeJob(JobInterface $job, GearmanJob $gearmanJob, Application $root)
+ public function executeJob(JobInterface $job, GearmanJob $gearmanJob, self $root): mixed
{
if ($root->getConfig()->getAutoUpdate() && !$root->isAllowingJob) {
$root->restart();
return null;
}
+
$root->isAllowingJob = false;
- if (null !== $root->logger) {
+
+ if ($root->logger !== null) {
$root->logger->info("Executing job {$job->getName()}");
}
+
return $job->execute($gearmanJob);
}
@@ -499,55 +499,37 @@ public function getProcess()
}
/**
- * @return LoggerInterface
+ * @return string
*/
- public function getLogger()
+ public function serialize(): string
{
- return $this->logger;
+ return serialize($this->__serialize());
}
- /**
- * @param LoggerInterface $logger
- * @return $this
- */
- public function setLogger(LoggerInterface $logger)
+ public function __serialize(): array
{
- $this->logger = $logger;
- return $this;
+ return [
+ 'config' => $this->config,
+ 'process' => $this->process,
+ 'callbacks' => $this->callbacks,
+ 'jobs' => $this->jobs,
+ 'isAllowingJob' => $this->isAllowingJob,
+ 'isBootstraped' => $this->isBootstraped
+ ];
}
- /**
- * @return string
- */
- public function serialize()
+ public function unserialize(string $data): void
{
- return serialize([
- 'config' => $this->getConfig(),
- 'isBootstraped' => false,
- 'isAllowingJob' => true
- ]);
+ $this->__unserialize(unserialize($data));
}
- /**
- * @param string $serialized
- */
- public function unserialize($serialized)
+ public function __unserialize(array $data): void
{
- $data = unserialize($serialized);
-
- if (isset($data['config'])) {
- $this->setConfig($data['config']);
- }
-
- $process = new Process($this->getConfig(), $this->getLogger());
- $this->setProcess($process);
-
- if (isset($data['isAllowingJob'])) {
- $this->isAllowingJob = $data['isAllowingJob'];
- }
-
- if (isset($data['isBootstraped'])) {
- $this->isBootstraped = $data['isBootstraped'];
- }
+ $this->config = $data['config'];
+ $this->process = $data['process'];
+ $this->callbacks = $data['callbacks'];
+ $this->jobs = $data['jobs'];
+ $this->isAllowingJob = $data['isAllowingJob'];
+ $this->isBootstraped = $data['isBootstraped'];
}
}
diff --git a/src/Worker.php b/src/Worker.php
index a22b76a..d923106 100644
--- a/src/Worker.php
+++ b/src/Worker.php
@@ -1,4 +1,6 @@
setConfig($config);
- if (null !== $logger) {
- $this->setLogger($logger);
- }
+ public function __construct(
+ Config $config,
+ ?LoggerInterface $logger = null
+ ) {
+ $this->config = $config;
+ $this->logger = $logger;
}
- public function resetWorker()
+ public function resetWorker(): void
{
if ($this->worker instanceof GearmanWorker) {
$this->worker->unregisterAll();
@@ -46,29 +48,34 @@ public function resetWorker()
}
/**
- * @throws Exception\ServerConnectionException
+ * @throws ServerConnectionException
*/
- private function createWorker()
+ private function createWorker(): void
{
$this->worker = new GearmanWorker();
- $servers = $this->getConfig()->getServers();
+ $servers = $this->config->getServers();
$exceptions = [];
+
foreach ($servers as $server) {
try {
$this->worker->addServer($server->getHost(), $server->getPort());
} catch (GearmanException $e) {
- $message = 'Unable to connect to Gearman Server ' . $server->getHost() . ':' . $server->getPort();
- if (null !== $this->logger) {
+ $message = sprintf(
+ 'Unable to connect to Gearman Server %s:%s',
+ $server->getHost(),
+ $server->getPort()
+ );
+
+ if ($this->logger !== null) {
$this->logger->info($message);
}
+
$exceptions[] = $message;
}
}
- if (count($exceptions)) {
- foreach ($exceptions as $exception) {
- throw new ServerConnectionException($exception);
- }
+ if (!empty($exceptions)) {
+ throw new ServerConnectionException(implode(', ', $exceptions));
}
}