Skip to content

Framework for asynchronous executing shell command in PHP.

Notifications You must be signed in to change notification settings

bucefal91/php-async

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

PHP asynchronous execution framework
------------------------------------

This framework allows you to execute asynchronously arbitrary shell command from
PHP process. It features the following functionality:
* open file descriptors for communication between the PHP process and the child
  one. Right now we support reading child's STDOUT and STDERR.
* ability to query whether the child process has finished its execution
* query PID of the child process, possibly for sending signals to it
* read exit code of the child process once it has finished its execution
* pre-inclined for easy caching of the child process results

------------------
Examples of usage:
------------------

Most simple asynchronous execution:
-----------------------------------
<?php
$command = 'my-command';
$args = array();
$args[] = array(
  'key' => '--name-of-the-argument',
  'glue' => ' ',
  'value' => 'value of the argument',
);

$child = new ToolsAsyncResult($cmd, $args);

// Your 'my-command --name-of-the-argument "value of the argument"' is being
// executed right now. In the mean time you can do something useful in your main
// PHP process.
do_something_useful();

// When you decide you need the results of asynchronous child process, simply do
// the following. If the command has not finished yet, your main PHP process
// will sleep until the execution is finished.
$result = $child->result();

if ($result['exit'] != 0) {
  // Whoups... The child process did not terminate with exit code 0.
  // Let's see, maybe there is more hints about what went wrong in the STDERR.
  $stderr = $result['stderr'];
}

// Now let's save the STDOUT from the child process somewhere.
$stdout = $result['stdout'];
?>

Run the asynchronous command and query whether it has finished:
---------------------------------------------------------------
<?php
$command = 'my-command';
$args = array();
$args[] = array(
  'key' => '--name-of-the-argument',
  'glue' => ' ',
  'value' => 'value of the argument',
);

$child = new ToolsAsyncResult($cmd, $args);

// While the child process is running, and as we do not want to sleep in the
// main PHP process waiting for the results, let's keep doing something useful.
while ($child->isRunning()) {
  do_something_useful();
}

// Now we fetched the child process results without actually sleeping a second
// in the main PHP process.
$result = $child->result();

?>

Additional file descriptors passed to your asynchronous command:
----------------------------------------------------------------
<?php
$command = 'my-awesome-command';
$args = array();

// Sometimes your command will communicate on more file descriptors than just
// STDOUT & STDERR. So you can provide additional file descriptors to your child
// command, be it a pipe or an actual file.
// See http://php.net/manual/en/function.proc-open.php for full list of
// available options.
$extra_descriptors = array(
  4 => array('pipe', 'w'),
);

$result = new ToolsAsyncResult($cmd, $args, NULL, array(), $extra_descriptors)->result();

// Let's see what our child command has communicated on the 4th file descriptor.
$fd4 = $result['streams'][4];
?>


Example of synchronous caching:
-------------------------------
<?php

/**
 * This function simply encapsulate starting a child process asynchronously.
 *
 * But let's put a bit on top of it. Before we take off to create a child
 * process, let's check if the results of $cmd are not available in cache. If
 * they are available, we return them right away without bothering with the
 * whole thing of asynchronous command.
 * Also, when the asynchronous command finishes execution, we take a note of its
 * result and if it's positive (exit code equals 0) we store it in the cache
 * bin. That way we guarantee asynchronous command will be only initiated for
 * commands that have not been run before.
 */
function do_something_asynchronously($cmd) {
  $cache = cache_bin_get($cmd);
  if ($cache) {
    // ToolsResult class has identical methods as the ToolsAsyncResult does,
    // but this one does not execute any asynchronous command, but simply stores
    // the $cache result until it is requested at some later point. That way we
    // can freely swap between ToolsResult and ToolsAsyncResult classes without
    // modifying the rest of our code.
    return new ToolsResult($cache);
  }
  return new ToolsAsyncResult($cmd, array(), 'my_process_callback', array($cmd));
}

/**
 * This function plays on par with do_something_asynchronously().
 *
 * When the child process has finished its execution, its results will be passed
 * into this process function before being returned to whoever have requested
 * them. We take the opportunity to store the results of asynchronous command
 * execution into our cache bin so next time they can be fetched much faster
 * from there.
 */
function my_process_callback($info, $cmd) {
  if ($info['exit'] == 0) {
    cache_bin_set($cmd, $info);
  }
  // We could also alter what gets returned to whoever requested the results of
  // asynchronous command execution by just returning something else than $info.
  // But let's keep this example simple.
  return $info;
}

$result = do_something_asynchronously('my-command');
// This line takes to execute as long as the asynchronous command takes to
// execute.
$result->result();

// But if we repeat the same thing over again, our results are already cached
// and this time it happens instantaneously. All you have to do, is to implement
// some cache storage bin.
$result = do_something_asynchronously('my-command');
$result->result();
?>

-----------------
Issues/Questions?
-----------------

Do check the php-async.php file to see full options and features provided by the
framework.

About

Framework for asynchronous executing shell command in PHP.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages