Skip to content

Commit

Permalink
Merge branch 'release/4.0.0'
Browse files Browse the repository at this point in the history
### Changed

- 27d0cc4: Add vendor namespace prefix and improve README.md.

### Fixed

- kriswallsmith#40: Do not lose fork messages after receive call.
  • Loading branch information
TheLevti committed Feb 9, 2020
2 parents ce608b4 + 5728319 commit 8f72492
Show file tree
Hide file tree
Showing 43 changed files with 174 additions and 132 deletions.
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [4.0.0] - 2020-02-09

### Changed

- 27d0cc4: Add vendor namespace prefix and improve README.md.

### Fixed

- kriswallsmith/spork#40: Do not lose fork messages after receive call.

## [3.0.0] - 2020-02-02

### Changed
Expand Down Expand Up @@ -72,7 +82,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added progress callbacks to Deferred.
- Added serializable objects for exit and error messages.

[Unreleased]: https://github.com/TheLevti/phpfork/compare/3.0.0...HEAD
[Unreleased]: https://github.com/TheLevti/phpfork/compare/4.0.0...HEAD
[4.0.0]: https://github.com/TheLevti/phpfork/releases/4.0.0
[3.0.0]: https://github.com/TheLevti/phpfork/releases/3.0.0
[2.0.2]: https://github.com/TheLevti/phpfork/releases/2.0.2
[2.0.1]: https://github.com/TheLevti/phpfork/releases/2.0.1
Expand Down
106 changes: 65 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,78 @@
# thelevti/phpfork

**[Requirements](#requirements)** |
**[Installation](#installation)** |
**[Usage](#usage)**

# thelevti/phpfork
[![Build Status][1]][2]

[![Build Status](https://travis-ci.com/TheLevti/phpfork.svg?branch=master)](https://travis-ci.com/TheLevti/phpfork)
A simple library to make forking a processes as easy as possible.

PHP on a fork.

`thelevti/phpfork` follows semantic versioning. Read more on [semver.org][1].
`thelevti/phpfork` follows semantic versioning. Read more on [semver.org][3].

----

## Requirements

- PHP 7.2 or above
- [php-pcntl][2] to allow this library forking processes.
- [php-posix][3] to allow this library getting process information.
- [php-shmop][4] to allow this library doing interprocess communication.
- PHP 7.2 or above
- [php-pcntl][4] to allow this library forking processes.
- [php-posix][5] to allow this library getting process information.
- [php-shmop][6] to allow this library doing interprocess communication.

----

## Installation

### Composer

To use this library through [composer][5], run the following terminal command
To use this library with [composer][7], run the following terminal command
inside your repository's root folder.

```sh
```bash
composer require "thelevti/phpfork"
```

## Usage

This library uses the namespace `Phpfork`.
This library uses the namespace `TheLevti\phpfork`.

### Example: Basic process forking

```php
<?php

$manager = new Phpfork\ProcessManager();
$manager->fork(function () {
// do something in another process!
return 'Hello from ' . getmypid();
})->then(function (Phpfork\Fork $fork) {
// do something in the parent process when it's done!
use TheLevti\phpfork\Fork;
use TheLevti\phpfork\ProcessManager;
use TheLevti\phpfork\SharedMemory;

$manager = new ProcessManager();
$fork = $manager->fork(function (SharedMemory $shm) {
// Do something in a forked process!
return 'Hello from ' . posix_getpid();
})->then(function (Fork $fork) {
// Do something in the parent process when the fork is done!
echo "{$fork->getPid()} says '{$fork->getResult()}'\n";
});

$manager->wait();
```

### Example: Upload images to your CDN
### Example: Upload images to a CDN

Feed an iterator into the process manager and it will break the job into
multiple batches and spread them across many processes.

```php
<?php

use TheLevti\phpfork\ProcessManager;
use SplFileInfo;

$files = new RecursiveDirectoryIterator('/path/to/images');
$files = new RecursiveIteratorIterator($files);

$manager = new Phpfork\ProcessManager();
$manager->process($files, function(SplFileInfo $file) {
$manager = new ProcessManager();
$batchJob = $manager->process($files, function(SplFileInfo $file) {
// upload this file
});

Expand All @@ -70,21 +81,31 @@ $manager->wait();

### Example: Working with Doctrine DBAL

When working with database connections, there is a known issue regarding parent/child processes.
From http://php.net/manual/en/function.pcntl-fork.php#70721:
When working with database connections, there is a known issue regarding
parent/child processes. See php doc for [pcntl_fork][8]:

> the child process inherits the parent's database connection.
> When the child exits, the connection is closed.
> If the parent is performing a query at this very moment, it is doing it on an already closed connection
> The reason for the MySQL "Lost Connection during query" issue when forking is
the fact that the child process inherits the parent's database connection. When
the child exits, the connection is closed. If the parent is performing a query
at this very moment, it is doing it on an already closed connection, hence the
error.

This will mean that in our example, we will see a `SQLSTATE[HY000]: General error: 2006 MySQL server has gone away`
exception being thrown in the parent process.
This will mean that in our example, we will see a `SQLSTATE[HY000]: General
error: 2006 MySQL server has gone away` exception being thrown in the parent
process.

One work-around for this situation is to force-close the DB connection before forking, by using the PRE_FORK event.
One work-around for this situation is to force-close the DB connection before
forking, by using the `PRE_FORK` event.

```php
<?php

use Doctrine\DBAL\DriverManager;
use TheLevti\phpfork\Batch\Strategy\ChunkStrategy;
use TheLevti\phpfork\EventDispatcher\Events;
use TheLevti\phpfork\EventDispatcher\SignalEventDispatcher;
use TheLevti\phpfork\ProcessManager;

$params = array(
'dbname' => '...',
'user' => '...',
Expand All @@ -98,7 +119,7 @@ $dataArray = range(0, 15);

$callback = function ($value) use ($params) {
// Child process acquires its own DB connection
$conn = Doctrine\DBAL\DriverManager::getConnection($params);
$conn = DriverManager::getConnection($params);
$conn->connect();

$sql = 'SELECT NOW() AS now';
Expand All @@ -111,18 +132,18 @@ $callback = function ($value) use ($params) {
};

// Get DB connection in parent
$parentConnection = Doctrine\DBAL\DriverManager::getConnection($params);
$parentConnection = DriverManager::getConnection($params);
$parentConnection->connect();

$dispatcher = new Phpfork\EventDispatcher\EventDispatcher();
$dispatcher->addListener(Phpfork\EventDispatcher\Events::PRE_FORK, function () use ($parentConnection) {
$dispatcher = new SignalEventDispatcher();
$dispatcher->addListener(Events::PRE_FORK, function () use ($parentConnection) {
$parentConnection->close();
});

$manager = new Phpfork\ProcessManager($dispatcher, null, true);
$manager = new ProcessManager($dispatcher, null, true);

/** @var Phpfork\Fork $fork */
$fork = $manager->process($dataArray, $callback, new Phpfork\Batch\Strategy\ChunkStrategy($forks));
/** @var TheLevti\phpfork\Fork $fork */
$fork = $manager->process($dataArray, $callback, new ChunkStrategy($forks));
$manager->wait();

$result = $fork->getResult();
Expand All @@ -135,8 +156,11 @@ $dbResult = $stmt->fetch();
$parentConnection->close();
```

[1]: https://semver.org
[2]: https://php.net/manual/en/book.pcntl.php
[3]: https://php.net/manual/en/book.posix.php
[4]: https://php.net/manual/en/book.shmop.php
[5]: https://getcomposer.org
[1]: https://travis-ci.com/TheLevti/phpfork.svg?branch=master
[2]: https://travis-ci.com/TheLevti/phpfork
[3]: https://semver.org
[4]: https://php.net/manual/en/book.pcntl.php
[5]: https://php.net/manual/en/book.posix.php
[6]: https://php.net/manual/en/book.shmop.php
[7]: https://getcomposer.org
[8]: http://php.net/manual/en/function.pcntl-fork.php#70721
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@
},
"autoload": {
"psr-4": {
"Phpfork\\": "src/"
"TheLevti\\phpfork\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Phpfork\\": "tests/"
"TheLevti\\phpfork\\": "tests/"
}
},
"suggest": {
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Phpfork Test Suite">
<testsuite name="phpfork Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
Expand Down
10 changes: 5 additions & 5 deletions src/Batch/BatchJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

declare(strict_types=1);

namespace Phpfork\Batch;
namespace TheLevti\phpfork\Batch;

use Phpfork\Batch\Strategy\ChunkStrategy;
use Phpfork\Batch\Strategy\StrategyInterface;
use Phpfork\Exception\UnexpectedTypeException;
use Phpfork\ProcessManager;
use TheLevti\phpfork\Batch\Strategy\ChunkStrategy;
use TheLevti\phpfork\Batch\Strategy\StrategyInterface;
use TheLevti\phpfork\Exception\UnexpectedTypeException;
use TheLevti\phpfork\ProcessManager;

class BatchJob
{
Expand Down
6 changes: 3 additions & 3 deletions src/Batch/BatchRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@

declare(strict_types=1);

namespace Phpfork\Batch;
namespace TheLevti\phpfork\Batch;

use Phpfork\Exception\UnexpectedTypeException;
use Phpfork\SharedMemory;
use TheLevti\phpfork\Exception\UnexpectedTypeException;
use TheLevti\phpfork\SharedMemory;

class BatchRunner
{
Expand Down
4 changes: 2 additions & 2 deletions src/Batch/Strategy/AbstractStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

declare(strict_types=1);

namespace Phpfork\Batch\Strategy;
namespace TheLevti\phpfork\Batch\Strategy;

use Phpfork\Batch\BatchRunner;
use TheLevti\phpfork\Batch\BatchRunner;

abstract class AbstractStrategy implements StrategyInterface
{
Expand Down
4 changes: 2 additions & 2 deletions src/Batch/Strategy/CallbackStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

declare(strict_types=1);

namespace Phpfork\Batch\Strategy;
namespace TheLevti\phpfork\Batch\Strategy;

use Phpfork\Exception\UnexpectedTypeException;
use TheLevti\phpfork\Exception\UnexpectedTypeException;

class CallbackStrategy extends AbstractStrategy
{
Expand Down
4 changes: 2 additions & 2 deletions src/Batch/Strategy/ChunkStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

declare(strict_types=1);

namespace Phpfork\Batch\Strategy;
namespace TheLevti\phpfork\Batch\Strategy;

use Phpfork\Exception\UnexpectedTypeException;
use TheLevti\phpfork\Exception\UnexpectedTypeException;

/**
* Creates the batch iterator using array_chunk().
Expand Down
2 changes: 1 addition & 1 deletion src/Batch/Strategy/StrategyInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

declare(strict_types=1);

namespace Phpfork\Batch\Strategy;
namespace TheLevti\phpfork\Batch\Strategy;

/**
* @see BatchJob::__invoke()
Expand Down
4 changes: 2 additions & 2 deletions src/Batch/Strategy/ThrottleStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

declare(strict_types=1);

namespace Phpfork\Batch\Strategy;
namespace TheLevti\phpfork\Batch\Strategy;

use Phpfork\Util\ThrottleIterator;
use TheLevti\phpfork\Util\ThrottleIterator;

class ThrottleStrategy implements StrategyInterface
{
Expand Down
4 changes: 2 additions & 2 deletions src/Deferred/Deferred.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

declare(strict_types=1);

namespace Phpfork\Deferred;
namespace TheLevti\phpfork\Deferred;

use Phpfork\Exception\UnexpectedTypeException;
use TheLevti\phpfork\Exception\UnexpectedTypeException;

class Deferred implements DeferredInterface
{
Expand Down
6 changes: 3 additions & 3 deletions src/Deferred/DeferredAggregate.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@

declare(strict_types=1);

namespace Phpfork\Deferred;
namespace TheLevti\phpfork\Deferred;

use Phpfork\Exception\UnexpectedTypeException;
use TheLevti\phpfork\Exception\UnexpectedTypeException;

class DeferredAggregate implements PromiseInterface
{
Expand All @@ -25,7 +25,7 @@ public function __construct(array $children)
// validate children
foreach ($children as $child) {
if (!$child instanceof PromiseInterface) {
throw new UnexpectedTypeException($child, 'Phpfork\Deferred\PromiseInterface');
throw new UnexpectedTypeException($child, 'TheLevti\phpfork\Deferred\PromiseInterface');
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/Deferred/DeferredInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

declare(strict_types=1);

namespace Phpfork\Deferred;
namespace TheLevti\phpfork\Deferred;

interface DeferredInterface extends PromiseInterface
{
Expand Down
2 changes: 1 addition & 1 deletion src/Deferred/PromiseInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

declare(strict_types=1);

namespace Phpfork\Deferred;
namespace TheLevti\phpfork\Deferred;

interface PromiseInterface
{
Expand Down
2 changes: 1 addition & 1 deletion src/EventDispatcher/Events.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

declare(strict_types=1);

namespace Phpfork\EventDispatcher;
namespace TheLevti\phpfork\EventDispatcher;

final class Events
{
Expand Down
2 changes: 1 addition & 1 deletion src/EventDispatcher/SignalEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

declare(strict_types=1);

namespace Phpfork\EventDispatcher;
namespace TheLevti\phpfork\EventDispatcher;

use Symfony\Contracts\EventDispatcher\Event as BaseEvent;

Expand Down
Loading

0 comments on commit 8f72492

Please sign in to comment.