Hi Guys,

In the world of web development, performance is key. As applications grow in complexity and the demand for responsiveness increases, managing tasks concurrently becomes crucial. This is where the Generic Executor Service for PHP comes into play. Designed to simplify and enhance the way PHP handles concurrent tasks, this library opens up new possibilities for developers.

Generic Executor Service in PHP
A Generic Executor Service in PHP library demonstrates a basic implementation of a Generic Executor Service in PHP 8 using the pcntl extension to handle concurrency. It mimics the behaviour of Java’s ExecutorService by managing a pool of “workers” (processes) that execute tasks asynchronously.

Generic Executor Service in PHP a language port from Java to PHP from the repository which I created a while ago called generic-executor-service-java (https://github.com/niteshapte/generic-executor-service-java)

Features

  • Task Submission: Submit tasks (callables) to be executed asynchronously by the worker pool.
  • Worker Pool Management: Limit the number of concurrent workers (processes) executing tasks.
  • Graceful Shutdown: Waits for all tasks to complete before shutting down.

Requirements

  • PHP 8.0+
  • pcntl extension enabled (usually available by default in most PHP installations, but needs to be enabled in some environments like Windows).

The GenericExecutorService Class

<?php
class GenericExecutorService {
    private array $workers = [];
    private int $maxWorkers;

    public function __construct(int $maxWorkers = 5) {
        $this->maxWorkers = $maxWorkers;
    }

    public function submit(callable $task) {
        if (count($this->workers) < $this->maxWorkers) {
            $pid = pcntl_fork();
            if ($pid == -1) {
                // Fork failed
                die('Could not fork process');
            } elseif ($pid) {
                // Parent process
                $this->workers[$pid] = $task;
            } else {
                // Child process
                $task();
                exit(0); // End the child process after task execution
            }
        } else {
            echo "Max workers reached, unable to submit new task.\n";
        }
    }

    public function shutdown() {
        foreach ($this->workers as $pid => $task) {
            pcntl_waitpid($pid, $status); // Wait for the child process to finish
            unset($this->workers[$pid]);  // Remove from worker pool
        }
    }
}
?>

Key Methods

execute(array $tasks): array

  • Description: This method takes an array of callable tasks and executes them concurrently. It returns an array of results.
  • Parameters:
    • $tasks: An array of callables that represent the tasks to be executed.
  • Returns: An array of results corresponding to the executed tasks.

submit(callable $task): void

  • Description: Submits a single task for execution and returns a Future object, which can be used to retrieve the result later.
  • Parameters:
    • $task: A callable representing the task to be executed.
  • Returns: Nothing.

shutdown(): void

  • Description: Cleans up any resources used by the executor service and ensures that all tasks have completed.
  • Returns: Nothing.

Handling Concurrency with pcntl

The GenericExecutorService relies on the pcntl_fork() function to create separate processes for each task. This provides concurrency in environments where PHP doesn’t natively support multi-threading. However, pcntl is only available in CLI and POSIX-compliant environments (Linux/macOS).

Compatibility

pcntl is not available on Windows, so this solution works best in Unix-like environments.

GitHub

https://github.com/niteshapte/generic-executor-service-php

 

That’s it.

Hope you liked it.

Critics/feedbacks are welcome.

Have a great day ahead!

Loading