Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
cursedcoder committed Sep 2, 2014
0 parents commit 79078e6
Show file tree
Hide file tree
Showing 24 changed files with 904 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
vendor
bin
composer.lock
tmp/*
107 changes: 107 additions & 0 deletions EProcess/Adapter/ChildProcess.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace EProcess\Adapter;

use EProcess\Behaviour\UniversalSerializer;
use EProcess\MessengerFactory;

use React\ChildProcess\Process;
use React\EventLoop\LoopInterface;
use Symfony\Component\Process\PhpExecutableFinder;

class ChildProcess
{
use UniversalSerializer;

private $script = <<<PHP
<?php
require_once '%s';
set_time_limit(0);
use EProcess\MessengerFactory;
use EProcess\Application\ApplicationFactory;
use React\EventLoop\Factory;
\$loop = Factory::create();
\$messenger = MessengerFactory::client(
'%s',
\$loop
);
\$application = ApplicationFactory::create('%s');
\$application->messenger(\$messenger);
\$application->loop(\$loop);
\$application->data(\$application->unserialize(base64_decode('%s')));
\$messenger->emit('initialized', true);
try {
\$application->run();
\$loop->run();
} catch (\Exception \$e) {
echo \$e;
}
PHP;

private $loop;
private $process;
private $executableFinder;

public function __construct(LoopInterface $loop)
{
$this->loop = $loop;
$this->executableFinder = new PhpExecutableFinder();
}

public function create($class, array $data = [])
{
if (false === $php = $this->executableFinder->find()) {
throw new \RuntimeException('Unable to find the PHP executable.');
}

$node = uniqid('thread_');
$unix = sprintf('unix://tmp/%s.sock', $node);

$messenger = MessengerFactory::server($unix, $this->loop);

$file = sprintf(__DIR__ . '/../../tmp/%s.php', $node);

file_put_contents($file, sprintf(
$this->script,
EPROCESS_AUTOLOAD,
$unix,
$class,
base64_encode($this->serialize($data))
));

$this->process = new Process(sprintf('exec %s %s', $php, realpath($file)));
$this->process->start($this->loop);

$this->loop->addTimer(5, function() use ($file) {
unlink($file);
});

$this->process->stdout->on('data', function($data) {
echo $data;
});

$this->process->stderr->on('data', function($data) {
echo $data;
});

register_shutdown_function(function() use ($unix) {
unlink($unix);
});

return $messenger;
}

public function kill()
{
$this->process->close();
}
}
35 changes: 35 additions & 0 deletions EProcess/Adapter/PThreads.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace EProcess\Adapter;

use EProcess\MessengerFactory;
use React\EventLoop\LoopInterface;

class PThreads
{
private $loop;
private $process;

public function __construct(LoopInterface $loop)
{
$this->loop = $loop;
}

public function create($class, array $data = [])
{
$node = uniqid('thread_');
$unix = sprintf('unix://tmp/%s.sock', $node);

$messenger = MessengerFactory::server($unix, $this->loop);

$this->process = new Thread($unix, $class, $data);
$this->process->start(PTHREADS_INHERIT_NONE);

return $messenger;
}

public function kill()
{
$this->process->kill();
}
}
75 changes: 75 additions & 0 deletions EProcess/Adapter/SymfonyProcess.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

namespace EProcess\Adapter;

use EProcess\Behaviour\UniversalSerializer;
use Symfony\Component\Process\PhpProcess;
use React\EventLoop\LoopInterface;
use EProcess\MessengerFactory;

class SymfonyProcess
{
use UniversalSerializer;

private $script = <<<PHP
<?php
require_once '%s';
set_time_limit(0);
use EProcess\MessengerFactory;
use EProcess\Application\ApplicationFactory;
use React\EventLoop\Factory;
\$loop = Factory::create();
\$messenger = MessengerFactory::client(
'%s',
\$loop
);
\$application = ApplicationFactory::create('%s');
\$application->messenger(\$messenger);
\$application->loop(\$loop);
\$application->data(\$application->unserialize(base64_decode('%s')));
\$messenger->emit('initialized', true);
try {
\$application->run();
\$loop->run();
} catch (\Exception \$e) {
echo \$e;
}
PHP;

private $loop;
private $process;

public function __construct(LoopInterface $loop)
{
$this->loop = $loop;
}

public function create($class, array $data = [])
{
$node = uniqid('thread_');
$unix = sprintf('unix://app/cache/%s.sock', $node);

$messenger = MessengerFactory::server($unix, $this->loop);

$script = sprintf($this->script, EPROCESS_AUTOLOAD, $unix, $class, base64_encode($this->serialize($data)));

$this->process = new PhpProcess($script);
$this->process->start();

return $messenger;
}

public function kill()
{
$this->process->stop();
}
}
44 changes: 44 additions & 0 deletions EProcess/Adapter/Thread.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace EProcess\Adapter;

use EProcess\Application\ApplicationFactory;
use EProcess\MessengerFactory;
use React\EventLoop\Factory;

class Thread extends \Thread
{
private $class;
private $unix;
private $data;

public function __construct($unix, $class, array $data)
{
$this->unix = $unix;
$this->class = $class;
$this->data = $data;
}

public function run()
{
require_once EPROCESS_AUTOLOAD;

$loop = Factory::create();

$messenger = MessengerFactory::client($this->unix, $loop);
$application = ApplicationFactory::create($this->class);

$application->messenger($messenger);
$application->loop($loop);
$application->data($this->data);

$messenger->emit('initialized', true);

try {
$application->run();
$loop->run();
} catch (\Exception $e) {
echo $e;
}
}
}
61 changes: 61 additions & 0 deletions EProcess/Application/Application.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace EProcess\Application;

use EProcess\Behaviour\UniversalSerializer;
use EProcess\Behaviour\Workable;
use Evenement\EventEmitterTrait;
use React\EventLoop\LoopInterface;
use EProcess\Messenger;
use EProcess\Message;

abstract class Application
{
use EventEmitterTrait {
EventEmitterTrait::emit as emitterEmit;
}
use UniversalSerializer;
use Workable;

private $loop;
private $messenger;
private $data;

public function loop(LoopInterface $loop = null)
{
if ($loop) {
$this->loop = $loop;
}

return $this->loop;
}

public function messenger(Messenger $messenger = null)
{
if ($messenger) {
$messenger->on('message', function(Message $message) {
$this->emitterEmit($message->getEvent(), [$message->getContent()]);
});

$this->messenger = $messenger;
}

return $this->messenger;
}

public function data(array $data = null)
{
if ($data) {
$this->data = $data;
}

return $this->data;
}

public function emit($event, $data)
{
$this->messenger->emit($event, $data);
}

abstract public function run();
}
34 changes: 34 additions & 0 deletions EProcess/Application/ApplicationFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace EProcess\Application;

use React\EventLoop\Factory;

class ApplicationFactory
{
public static function launch($fqcn)
{
$application = static::create($fqcn);

try {
$application->run();
$application->loop()->run();
} catch (\Exception $e) {
echo $e;
}
}

public static function create($fqcn)
{
if (!is_subclass_of($fqcn, Application::class)) {
throw new \InvalidArgumentException('Should be a subclass of Application');
}

$loop = Factory::create();

$application = new $fqcn();
$application->loop($loop);

return $application;
}
}
Loading

0 comments on commit 79078e6

Please sign in to comment.