publicplan/parallel-bridge

Symfony Parallel Bridge

Installs: 13 959

Dependents: 0

Suggesters: 0

Security: 0

Stars: 3

Watchers: 2

Forks: 0

Open Issues: 0

Type:symfony-bundle

v1.1.2 2021-01-18 15:34 UTC

This package is auto-updated.

Last update: 2024-04-18 22:44:35 UTC


README

Version MIT License Symfony Pipeline

Provides utilities from AMPHP Parallel, especially parallel functions. This Bundle is developed and tested with php 7.3, 7.4 and 8.0 and Symfony 4.4 and 5.2. Other Versions might work but are not supported or tested.

SETUP

  1. Use composer to install Parallel-Bridge.
composer require publicplan/parallel-bridge
  1. Create worker-bootstrap.php in your application config folder.
// app/config/worker-bootstrap.php
<?php

declare(strict_types=1);

use App\Kernel;
use Symfony\Component\Dotenv\Dotenv;

set_time_limit(0);

if (class_exists(Dotenv::class)) {
    if (method_exists(Dotenv::class, 'bootenv')) {
        (new Dotenv())->bootEnv(dirname(__DIR__) . '/.env');
    } else {
        require dirname(__DIR__) . '/config/bootstrap.php';
    }
}

$kernel = new Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']);
$kernel->boot();
$GLOBALS['kernel'] = $kernel;
  1. Create parallel_bridge.yaml in your config/packages dir.
# config/packages/parallel_bridge.yaml
publicplan_parallel_bridge:
  amphp_max_worker: '%env(int:AMPHP_MAX_WORKERS)%'
  project_dir: '%kernel.project_dir%'
  1. Setup your maximal worker amount in your .env.local.
AMPHP_MAX_WORKERS=3

info: fill in a "0" for synchronous execution without workers. This can be handy for debugging and some rare Problems with Macs.

Usage

  1. Use PromiseWait in your class to remap async! You can use any callable you like but you should consider that closures must be serializable. When you need your projects context we recommend to use the following way: (also see https://amphp.org/parallel-functions/ for deeper information)
// src/Service/YourClass.php
<?php

declare(strict_types=1);

namespace App\Service;

use Amp\MultiReasonException;
use Publicplan\ParallelBridge\PromiseWaitInterface;

class YourClass
{
    /** @var PromiseWaitInterface */
    private $promiseWait;

    public function __construct(PromiseWaitInterface $promiseWait)
    {
        $this->promiseWait = $promiseWait;
    }

    public function yourFunction(): void
    {
        $unprocessDataArray = range(1, 100);

        try{
            //If we want to use a container class it must be public and in the following format:
            $finalDataArray = $this->promiseWait->parallelMap($unprocessDataArray, [$this,'processSingleElement']);
        } 
        //to get possible errors you have to catch MultiReasonException 
        catch (MultiReasonException $exception ){
            dd($exception);
        }
        print_r($finalDataArray);
    }

    //This Function will be called async from our processes after grabbing this service from service container
    public function processSingleElement(int $number): string
    {
        for ($i = 0; $i < 200000; $i++) {
         $hash =  hash('SHA512', (string)$number);
        }
        return $hash;
    }
}
  1. Make your service public! When using a service, like we do in the example above, you need to make your service public.
# config/services.yaml
services:
    [...]
    App\Service\YourClass:
        public: true

Optional: Additional Arguments

Add additional arguments to the PromiseWait::parallelMap() function as you like. All arguments get passed through to your called function.

<?php

declare(strict_types=1);

namespace App\Service;

use Publicplan\ParallelBridge\PromiseWaitInterface;

class YourClass
{
    /** @var PromiseWaitInterface */
    private $promiseWait;

    public function __construct(PromiseWaitInterface $promiseWait)
    {
        $this->promiseWait = $promiseWait;
    }
    
    public function yourFunction(): void
    {
        $unprocessDataArray = range(1, 100);
        $additionalArg = 42;

        $result = $this->promiseWait->parallelMap(
           $unprocessDataArray, 
           [$this,'processSingleElement'],
           $additionalArg,
        );
        
        //Returns numbers from 43 to 143
        print_r($result);
    }

    public function processSingleElement(int $number, int $additionalArg): int
    {
        return $number + $additionalArg;
    }
}