Skip to content

Commit

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

- #1: PHP 7.2 min requirement and updated library to support it.
- #4: Added DBAL usage documentation and updated existing examples.
- 2d0951d: Applied PSR12 and additional rules to library.

### Removed

- #1: Removed support for PHP <7.2
  • Loading branch information
TheLevti committed Nov 29, 2019
2 parents 530fcf5 + 537248c commit 5d575ca
Show file tree
Hide file tree
Showing 39 changed files with 729 additions and 446 deletions.
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/php_cs.dist export-ignore
/phpunit.xml.dist export-ignore
/tests export-ignore
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
composer.lock
composer.phar
phpunit.xml
vendor/
/.php_cs
/.phpunit.result.cache
/composer.lock
/phpunit.xml
/vendor
54 changes: 54 additions & 0 deletions .php_cs.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

$finder = PhpCsFixer\Finder::create()
->notPath('vendor')
->in(__DIR__)
->name('*.php')
->ignoreDotFiles(true)
->ignoreVCS(true);

return PhpCsFixer\Config::create()
->setUsingCache(false)
->setRiskyAllowed(true)
->setRules([
'@PSR2' => true,
'psr4' => true,
'binary_operator_spaces' => true,
'array_syntax' => ['syntax' => 'short'],
'linebreak_after_opening_tag' => true,
'not_operator_with_successor_space' => true,
'no_unused_imports' => true,
'not_operator_with_successor_space' => false,
'object_operator_without_whitespace' => true,
'ordered_imports' => true,
'phpdoc_order' => true,
'blank_line_before_return' => true,
'single_quote' => true,
'blank_line_after_opening_tag' => true,
'no_extra_blank_lines' => [
'extra',
'continue',
'curly_brace_block',
'parenthesis_brace_block',
'return',
'square_brace_block',
'throw',
'use',
'use_trait',
'switch',
'case',
'default',
],
'no_whitespace_in_blank_line' => true,
'no_blank_lines_after_class_opening' => true,
'return_type_declaration' => [
'space_before' => 'none',
],
'concat_space' => [
'spacing' => 'one',
],
'compact_nullable_typehint' => true,
'ternary_operator_spaces' => true,
'unary_operator_spaces' => true,
])
->setFinder($finder);
26 changes: 19 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
language: php

sudo: false

cache:
directories:
- $HOME/.composer/cache

php:
- 5.3
- 5.4
- 5.5
- 7.2
- 7.3
- nightly

matrix:
fast_finish: true
allow_failures:
- php: nightly

before_script:
- wget http://getcomposer.org/composer.phar
- php composer.phar install --dev
install:
- composer install --no-progress --no-scripts --no-suggest --no-interaction

script: phpunit --coverage-text
script:
- vendor/bin/phpunit --coverage-text
- vendor/bin/phpcs --standard=PSR12 src/ tests/
37 changes: 31 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
## 0.3 (May 18, 2015)
# Changelog

* Changed ProcessManager constructor to accept new Factory class as second
argument
* Use shared memory for interprocess communications (@MattJaniszewski)
* Added progress callbacks to Deferred
* Added serializable objects for exit and error messages
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [1.0.0] - 2019-11-29

### Changed

- #1: PHP 7.2 min requirement and updated library to support it.
- #4: Added DBAL usage documentation and updated existing examples.
- 2d0951d: Applied PSR12 and additional rules to library.

### Removed

- #1: Removed support for PHP <7.2

## [0.3.0] - 2015-05-18

### Changed

- Changed ProcessManager constructor to accept new Factory class as second argument.
- Use shared memory for interprocess communications (@MattJaniszewski).
- Added progress callbacks to Deferred.
- Added serializable objects for exit and error messages.

[Unreleased]: https://github.com/TheLevti/spork/compare/0.3.0...HEAD
[0.3.0]: https://github.com/TheLevti/spork/releases/0.3.0
25 changes: 12 additions & 13 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
Copyright (c) 2012-2013 OpenSky Project Inc
Copyright 2019 Petr Levtonov <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
121 changes: 115 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,49 @@
[![Build Status](https://secure.travis-ci.org/kriswallsmith/spork.png?branch=master)](http://travis-ci.org/kriswallsmith/spork)
**[Requirements](#requirements)** |
**[Installation](#installation)** |
**[Usage](#usage)**

Spork: PHP on a Fork
--------------------
# thelevti/spork

[![Build Status](https://travis-ci.com/TheLevti/spork.svg?branch=master)](https://travis-ci.com/TheLevti/spork)

PHP on a fork.

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

----

## 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.

----

## Installation

### Composer

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

```sh
composer require "thelevti/spork"
```

## Usage

This library uses the namespace `Spork`.

```php
<?php

$manager = new Spork\ProcessManager();
$manager->fork(function() {
$manager->fork(function () {
// do something in another process!
return 'Hello from '.getmypid();
})->then(function(Spork\Fork $fork) {
return 'Hello from ' . getmypid();
})->then(function (Spork\Fork $fork) {
// do something in the parent process when it's done!
echo "{$fork->getPid()} says '{$fork->getResult()}'\n";
});
Expand All @@ -27,7 +60,83 @@ multiple batches and spread them across many processes.
$files = new RecursiveDirectoryIterator('/path/to/images');
$files = new RecursiveIteratorIterator($files);

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

$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:

> 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
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.

```php
<?php

$params = array(
'dbname' => '...',
'user' => '...',
'password' => '...',
'host' => '...',
'driver' => 'pdo_mysql',
);

$forks = 4;
$dataArray = range(0, 15);

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

$sql = 'SELECT NOW() AS now';
$stmt = $conn->prepare($sql);
$stmt->execute();
$dbResult = $stmt->fetch();
$conn->close();

return ['pid' => getmypid(), 'value' => $value, 'result' => $dbResult];
};

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

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

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

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

$result = $fork->getResult();

// Safe to use now
$sql = 'SELECT NOW() AS now_parent';
$stmt = $parentConnection->prepare($sql);
$stmt->execute();
$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
Loading

0 comments on commit 5d575ca

Please sign in to comment.