Skip to content

Commit

Permalink
bump 1.0.9
Browse files Browse the repository at this point in the history
Added: verbose option.
  • Loading branch information
nawawi committed Jul 8, 2021
1 parent a97abba commit b5e201a
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 39 deletions.
51 changes: 46 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ Execute WordPress cron events in parallel.

Docket CronWP is a command-line tool for executing WordPress cron events in parallel.

This tool is part of the [Docket Cache](https://docketcache.com) project.

## Requirements
- UNIX-like environment (OS X, Linux, FreeBSD, Cygwin, WSL)
- PHP >= 7.2.5
- WordPress >= 5.4
- PHP pnctl extension
- PHP [pnctl](https://www.php.net/manual/en/book.pcntl.php) extension

## Installation

Expand Down Expand Up @@ -39,29 +41,38 @@ Disable the built in WordPress cron in `wp-config.php`:
define( 'DISABLE_WP_CRON', true );
```

Updating to the latest version:

```sh
sudo wget https://github.com/nawawi/docket-cronwp/raw/main/bin/docket-cronwp.phar -O /usr/local/bin/cronwp
sudo chmod +x /usr/local/bin/cronwp

```

## Usage
```
$ cronwp -h
Docket CronWP v1.0.8.
Docket CronWP v1.0.9.
Execute WordPress cron events in parallel.
Usage:
cronwp [<path>|<options>]
docket-cronwp.phar [<path>|<options>]
Path:
Path to the WordPress files.
Options:
-p --path <path> Path to the WordPress files.
-j --jobs <number> Run number of events in parallel.
-j --jobs <number> Run number of events in parallel (default: 3).
-u --url <url> Multisite target URL.
-a --run-now Run all cron event.
-t --dry-run Run without execute cron event.
-h --help Display this help message.
-q --quiet Suppress output.
-v --verbose Display additional output.
--debug Display debugging output.
-V --version Display version.
-h --help Display this help message.
```

## Example
Expand Down Expand Up @@ -139,6 +150,36 @@ status : success
....
```

Run with debugging output:

```sh
cronwp /path-to/wordpress --jobs 3 --run-now --quiet --debug
```

Output:
```
# 1625731052.7421 : Process-begin : 53132 : Processing 15 events, where every 3 events are run in parallel.
# 1625731052.7432 : Forked : 53133 : for event 'docketcache_gc'
# 1625731052.7434 : Callback-begin : 53133 : for event 'docketcache_gc'.
# 1625731052.7833 : Callback-done : 53133 : for event 'docketcache_gc'.
# 1625731052.8051 : Parent-closed : 53133 : for event 'docketcache_gc'.
# 1625731052.8063 : Forked : 53134 : for event 'docketcache_watchproc'
# 1625731052.8064 : Callback-begin : 53134 : for event 'docketcache_watchproc'.
# 1625731052.8501 : Callback-done : 53134 : for event 'docketcache_watchproc'.
# 1625731052.8698 : Parent-closed : 53134 : for event 'docketcache_watchproc'.
# 1625731052.8709 : Forked : 53135 : for event 'wp_privacy_delete_old_export_files'
# 1625731052.8710 : Callback-begin : 53135 : for event 'wp_privacy_delete_old_export_files'.
# 1625731052.8715 : Callback-done : 53135 : for event 'wp_privacy_delete_old_export_files'.
# 1625731052.8918 : Parent-closed : 53135 : for event 'wp_privacy_delete_old_export_files'.
# 1625731052.8923 : Wait-begin : 53132 : Waiting 3 events to finish.
# 1625731052.8923 : Child-closed : 53133 : for event 'docketcache_gc'.
# 1625731052.8926 : Child-closed : 53134 : for event 'docketcache_watchproc'.
# 1625731052.8927 : Child-closed : 53135 : for event 'wp_privacy_delete_old_export_files'.
# 1625731052.8927 : Wait-done : 53132 : Processing next 3 events.
....
```

Run WordPress cron with 3 events execute in parallel using server cron. Edit `/etc/crontab` and insert command below:

```
Expand Down
Binary file modified bin/docket-cronwp.phar
Binary file not shown.
2 changes: 1 addition & 1 deletion docket-cronwp.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
'DOCKET_CRONWP',
[
'NAME' => 'Docket CronWP',
'VERSION' => '1.0.8',
'VERSION' => '1.0.9',
'ROOT' => __DIR__,
'SELF' => !empty($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : __FILE__,
]
Expand Down
23 changes: 13 additions & 10 deletions includes/src/Bepart.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,11 @@ private function strip_proto($url)
private function rowh(string $name, string $pad = ' ', int $minlen = 15)
{
$len = $minlen - \strlen($name);

return $name.str_repeat($pad, $len);
}

private function result_export($data)
{
$output = '';
foreach ($data as $name => $value) {
$output .= $this->rowh($name).': '.$value.\PHP_EOL;
if ($len < 0) {
$len = $minlen;
}

return $output;
return $name.str_repeat($pad, $len);
}

private function output($text, $is_error = false)
Expand All @@ -63,6 +56,16 @@ private function output($text, $is_error = false)
fwrite($fd, $text);
}

private function output_debug($title, $pid, $msg)
{
if (isset($this->args['debug']) && $this->args['debug']) {
$time = $this->rowh(sprintf('%.4F', microtime(true)), ' ', 16);
$title = $this->rowh($title);
$pid = $this->rowh($pid, ' ', 7);
$this->output('# '.$time.': '.$title.': '.$pid.': '.$msg.\PHP_EOL);
}
}

private function get_hash($string)
{
return substr(md5($string), 0, 12);
Expand Down
50 changes: 36 additions & 14 deletions includes/src/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ final class Console
'help' => false,
'version' => false,
'verbose' => false,
'debug' => false,
];

public function __construct()
Expand Down Expand Up @@ -83,14 +84,15 @@ private function print_usage()
$text .= ' Path to the WordPress files.'.\PHP_EOL.\PHP_EOL;
$text .= 'Options:'.\PHP_EOL;
$text .= ' -p --path <path> Path to the WordPress files.'.\PHP_EOL;
$text .= ' -j --jobs <number> Run number of events in parallel.'.\PHP_EOL;
$text .= ' -j --jobs <number> Run number of events in parallel (default: '.$this->args['job'].').'.\PHP_EOL;
$text .= ' -u --url <url> Multisite target URL.'.\PHP_EOL;
$text .= ' -a --run-now Run all cron event.'.\PHP_EOL;
$text .= ' -t --dry-run Run without execute cron event.'.\PHP_EOL;
$text .= ' -h --help Display this help message.'.\PHP_EOL;
$text .= ' -q --quiet Suppress output.'.\PHP_EOL;
$text .= ' -v --verbose Display additional output.'.\PHP_EOL;
$text .= ' --debug Display debugging output.'.\PHP_EOL;
$text .= ' -V --version Display version.'.\PHP_EOL;
$text .= ' -h --help Display this help message.'.\PHP_EOL;
$this->output($text);
}

Expand Down Expand Up @@ -135,15 +137,14 @@ private function register_args()
case 'verbose':
$this->args['verbose'] = $this->get_bool($key, false);
break;
case 'debug':
$this->args['debug'] = $this->get_bool($key, false);
break;
case 'j':
case 'jobs':
$job = (int) $value;
$this->args['job'] = $job < 0 ? 1 : $job;
break;
case 'n':
case 'network':
$this->args['network'] = $this->get_bool($key, false);
break;
case 'u':
case 'url':
if (!$this->get_bool($key, false)) {
Expand Down Expand Up @@ -283,11 +284,16 @@ function ($lockfile) use ($lock_file) {

// ctrl+c
pcntl_signal(\SIGINT, function ($signo) use ($lock_file) {
$this->output('Exiting.. cleanup lock files.'.\PHP_EOL);
if (is_file($lock_file) && is_writable($lock_file)) {
@unlink($lock_file);
static $done = false;

if (!$done) {
$done = true;
$this->output('Exiting.. cleanup lock files.'.\PHP_EOL);
if (is_file($lock_file) && is_writable($lock_file)) {
@unlink($lock_file);
}
$this->cleanup();
}
$this->cleanup();
exit(0);
});

Expand Down Expand Up @@ -346,17 +352,21 @@ function ($arr) use ($wp_get_schedules) {

unset($crons, $cronhooks);

$mypid = getmypid();
$this->output_debug('Process-begin', $mypid, 'Processing '.\count($collect).' events, where every '.$this->args['job'].' events are run in parallel.');

if (!empty($collect)) {
$cnt = 0;
$max = $this->args['job'];

$num = 0;
$all = \count($collect);
foreach ($collect as $hook => $args) {
++$cnt;

++$num;
$this->proc_fork(
$hook,
function () use ($hook, $args) {
$timer_start = microtime(true);
$timer_start = sprintf('%.4F', microtime(true));
$status = true;
$error = '';
$content = '';
Expand All @@ -373,7 +383,7 @@ function () use ($hook, $args) {
}
}

$timer_stop = microtime(true);
$timer_stop = sprintf('%.4F', microtime(true));

$data = [
'pid' => '',
Expand All @@ -397,7 +407,18 @@ function () use ($hook, $args) {
);

if ($cnt >= $max) {
$this->output_debug('Wait-begin', $mypid, 'Waiting '.$cnt.' events to finish.');
$this->proc_wait();

$nx = $all - $num;
if ($nx > $max) {
$nx = $cnt;
}

if ($nx > 0) {
$this->output_debug('Wait-done', $mypid, 'Processing next '.$nx.' events.');
}

$cnt = 0;
}
}
Expand Down Expand Up @@ -428,6 +449,7 @@ function () use ($hook, $args) {
delete_transient('doing_cron');
}

$this->output_debug('Process-done', $mypid, 'Exiting.');
exit(0);
}
}
40 changes: 31 additions & 9 deletions includes/src/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ private function proc_get($key, $hook)
return false;
}

private function proc_output($data)
{
$output = '';
foreach ($data as $name => $value) {
$output .= $this->rowh($name).': '.$value.\PHP_EOL;
}

return $output;
}

private function proc_fork($name, $callback)
{
if (!\is_callable($callback)) {
Expand All @@ -65,46 +75,58 @@ private function proc_fork($name, $callback)

return false;
}

if ($pid) {
$this->pids[$name] = $pid;

$this->output_debug('Forked', $pid, "for event '".$name."'");

// prevent zombie
pcntl_wait($status);

$this->output_debug('Parent-closed', $pid, "for event '".$name."'.");

// we're parent, db already close, reconnect
$this->wpdb_reconnect();

return true;
}

$pid = getmypid();
$this->output_debug('Callback-begin', $pid, "for event '".$name."'.");

\call_user_func($callback);

$this->output_debug('Callback-done', $pid, "for event '".$name."'.");
exit(0);
}

private function proc_wait($cleanup = false)
private function proc_wait()
{
if (empty($this->pids)) {
return false;
}

$pids = array_keys($this->pids);
foreach ($pids as $key) {
if (!isset($this->pids[$key])) {
foreach ($pids as $name) {
if (!isset($this->pids[$name])) {
continue;
}

$pid = $this->pids[$key];
pcntl_waitpid($this->pids[$key], $status);
unset($this->pids[$key]);
$pid = $this->pids[$name];
pcntl_waitpid($pid, $status);
unset($this->pids[$name]);

$this->output_debug('Child-closed', $pid, "for event '".$name."'.");

$result = $this->proc_get($this->key, $key);
$result = $this->proc_get($this->key, $name);
if (!empty($result) && \is_array($result)) {
if (!$this->args['quiet']) {
$time = ($result['timer_stop'] - $result['timer_start']);
$this->output('Executed the cron event \''.$key.'\' in '.number_format($time, 3).'s'.\PHP_EOL);
$this->output('Executed the cron event \''.$name.'\' in '.number_format($time, 3).'s.'.\PHP_EOL);
if ($this->args['verbose']) {
$result['pid'] = $pid;
$this->output($this->result_export($result).\PHP_EOL);
$this->output($this->proc_output($result).\PHP_EOL);
}
}
}
Expand Down

0 comments on commit b5e201a

Please sign in to comment.