Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Simple Fork Laravel Package

jenner/simple_fork

SimpleFork is a PHP PCNTL-based multi-process framework with Java-like Thread/Runnable APIs. It provides process pools, automatic zombie recovery, signal handling, and IPC options like shared memory, SysV queues/semaphores, file locks, and Redis queues/cache.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require jenner/simple_fork
    

    Ensure ext-pcntl is enabled in php.ini.

  2. First use case: Run a one-off process

    use Jenner\SimpleFork\Process;
    
    $process = new Process(function() {
        echo "Hello from child process!\n";
    });
    $process->start();
    $process->wait(); // Block until completion
    
  3. Key files to explore:

    • src/Process.php: Core process class (extend or use with callbacks).
    • src/Pool.php: Basic process pool (for heterogeneous tasks).
    • src/FixedPool.php: Fixed-size worker pool (for homogeneous tasks).
    • src/Cache/, src/Queue/, src/Lock/: IPC/sync implementations.

Implementation Patterns

1. Process Creation

Option A: Callback (Quick & Dirty)

$process = new Process(function() {
    // Task logic here
});
$process->start();

Use when: One-off tasks or simple scripts.

Option B: Extend Process (Reusable Workers)

class ImageProcessor extends Process {
    protected $imagePath;

    public function __construct(string $imagePath) {
        $this->imagePath = $imagePath;
    }

    public function run() {
        // Process image logic
        file_put_contents("processed_{$this->imagePath}", $this->processImage());
    }
}

Use when: Reusable workers with state (e.g., config, dependencies).

Option C: Implement Runnable (Interface-Based)

class RunnableTask implements Runnable {
    public function run() {
        // Task logic
    }
}

$process = new Process(new RunnableTask());

Use when: Dependency injection or testing (easier to mock).


2. Process Pools

Pool (Dynamic)

$pool = new Pool();
$pool->execute(new Process(new RunnableTask()));
$pool->execute(new Process(new AnotherTask()));
$pool->wait(); // Blocks until all processes finish

Use when: Heterogeneous tasks (e.g., mixed batch jobs).

FixedPool (Controlled Concurrency)

$pool = new FixedPool(4); // Max 4 concurrent workers
$pool->execute(new Process(new RunnableTask()));
// ... add more tasks
$pool->wait();

Use when: CPU-bound tasks with resource limits (e.g., API rate limits).

SinglePool (Serial with Overlap)

$pool = new SinglePool();
$pool->execute(new Process(new RunnableTask()));
// Next task starts only after previous finishes

Use when: Sequential dependency (e.g., pipeline stages).

ParallelPool (Fixed + Auto-Reload)

$pool = new ParallelPool(new RunnableTask(), 3); // 3 workers
$pool->start();
$pool->keep(true); // Run indefinitely (e.g., for consumers)

Use when: Long-running services (e.g., Kafka consumers, WebSocket handlers).


3. Inter-Process Communication (IPC)

Shared Memory (Fast, Local)

$cache = new \Jenner\SimpleFork\Cache\SharedMemory();
$cache->set('key', 'value'); // Parent
// ...
$value = $cache->get('key'); // Child

Use when: High-speed data sharing between processes (e.g., caching).

Redis (Distributed)

$cache = new \Jenner\SimpleFork\Cache\RedisCache();
$cache->set('key', 'value');

Use when: Cross-machine coordination or persistence.

Message Queues (Async)

$queue = new \Jenner\SimpleFork\Queue\RedisQueue();
$queue->put('task_data'); // Producer
// ...
$data = $queue->get();    // Consumer

Use when: Decoupled producers/consumers (e.g., background jobs).

Semaphores (Synchronization)

$sem = \Jenner\SimpleFork\Lock\Semaphore::create('lock_key');
$sem->acquire();  // Block until available
// Critical section
$sem->release();

Use when: Mutual exclusion (e.g., file locks, rate limiting).


4. Integration with Laravel

Artisan Commands

use Jenner\SimpleFork\Process;
use Illuminate\Console\Command;

class ProcessCommand extends Command {
    public function handle() {
        $process = new Process(function() {
            // Heavy task
        });
        $process->start();
        $this->info("Process started (PID: {$process->getPid()})");
    }
}

Use when: CLI-driven parallel tasks (e.g., php artisan process:images).

Queue Workers (Alternative to Laravel Queues)

// config/queue.php
'connections' => [
    'simple_fork' => [
        'driver' => 'simple_fork',
        'pool' => FixedPool::class,
        'size' => 5,
    ],
],

Use when: Replacing Laravel’s queue system for CPU-bound jobs.

Service Providers

public function register() {
    $this->app->singleton('process.pool', function() {
        return new FixedPool(4);
    });
}

Use when: Centralized process management (e.g., for microservices).


5. Signal Handling

// In master process
pcntl_signal(SIGTERM, function() {
    $pool->shutdown(); // Graceful exit
});

// In child process
Process::registerSignalHandler(SIGTERM, function() {
    // Cleanup
});

Use when: Handling SIGTERM/SIGINT for graceful shutdowns.


Gotchas and Tips

Pitfalls

  1. Zombie Processes

    • Issue: Forgetting wait() can leave orphaned processes.
    • Fix: Always call wait() or use Pool::shutdown().
    • Debug: Check ps aux | grep php for stragglers.
  2. Signal Handling

    • Issue: Child processes inherit master’s signal handlers unless overridden.
    • Fix: Use Process::registerSignalHandler() before start().
    • Tip: Avoid declare(ticks=1)—use pcntl_signal_dispatch() instead.
  3. Shared Resources

    • Issue: File handles/sockets leak in child processes.
    • Fix: Reopen connections in each child (e.g., new Redis() per process).
    • Tip: Use RedisCluster or connection pooling for high-throughput.
  4. IPC Limitations

    • Issue: Shared memory (sysvshm) is local-only (no cross-server).
    • Fix: Use Redis for distributed IPC.
    • Tip: SysV queues (sysvmsg) have size limits (~8KB per message).
  5. FixedPool Reload

    • Issue: reload() kills old processes abruptly.
    • Fix: Implement graceful shutdown hooks in child run() methods.
  6. PHP Version

    • Issue: Last release (2017) may not support PHP 8+.
    • Fix: Test with declare(strict_types=1) and polyfills if needed.

Debugging Tips

  1. Log Process IDs

    echo "Master PID: " . getmypid() . "\n";
    $process->start();
    echo "Child PID: " . $process->getPid() . "\n";
    
  2. Check Exit Codes

    $process->wait();
    if ($process->getExitCode() !== 0) {
        throw new \RuntimeException("Process failed");
    }
    
  3. Use strace for Hangs

    strace -p <PID>  # Debug blocked processes
    
  4. Monitor with htop

    htop -p $(pgrep php)  # Watch process resource usage
    

Extension Points

  1. Custom IPC

    • Extend CacheInterface, QueueInterface, or LockInterface for new backends (e.g., database locks).
  2. Process Lifecycle Hooks

    class MyProcess extends Process {
        public function onStart() { /* Pre-run */ }
        public function onExit() { /* Post-run */ }
    }
    
  3. Dynamic Pool Sizing

    $pool = new FixedPool(4);
    // Later...
    $pool->setSize(8); // Resize (requires reload)
    
  4. Error Handling

    $process->onError(function($exitCode, $signal) {
        // Log or retry
    });
    

Performance Quirks

  1. Overhead of fork()

    • Tip: Batch small tasks into larger processes to amortize fork cost.
  2. Redis vs. SysV

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor