diff --git a/README.md b/README.md index b66dd3c..2c3a3c7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# ![Docket CronWP](./.docketcache.com/icon-128x128.png) Docket CronWP +![Docket CronWP](./.docketcache.com/icon-128x128.png) +# Docket CronWP Execute WordPress cron events in parallel. @@ -42,7 +43,7 @@ define( 'DISABLE_WP_CRON', true ); ``` cronwp -h -Docket CronWP v1.0.4 +Docket CronWP v1.0.5 Execute WordPress cron events in parallel. Usage: @@ -68,24 +69,46 @@ Run WordPress cron with 3 events execute in parallel: cronwp /path-to/wordpress --jobs 3 ``` -Results: +Output: ``` -Executed the cron event 'wp_https_detection' in 0.006s +Executed the cron event 'wp_update_plugins' in 2.163s [ - hook => wp_https_detection - timer_start => 1624752922.008 - timer_stop => 1624752922.014 + pid => 43406 + time => 2021-06-28 02:14:53 + hook => wp_update_plugins + timer_start => 1624846493.252183 + timer_stop => 1624846495.415512 status => true - pid => 350128 ] -Executed the cron event 'wp_update_plugins' in 0.094s +Executed the cron event 'wp_update_themes' in 0.006s [ - hook => wp_update_plugins - timer_start => 1624752922.917 - timer_stop => 1624752923.011 + pid => 43407 + time => 2021-06-28 02:14:53 + hook => wp_update_themes + timer_start => 1624846493.253142 + timer_stop => 1624846493.259058 + status => true +] + +Executed the cron event 'wp_scheduled_delete' in 0.003s +[ + pid => 43408 + time => 2021-06-28 02:14:53 + hook => wp_scheduled_delete + timer_start => 1624846493.254066 + timer_stop => 1624846493.256793 + status => true +] + +Executed the cron event 'delete_expired_transients' in 0.000s +[ + pid => 43418 + time => 2021-06-28 02:14:55 + hook => delete_expired_transients + timer_start => 1624846495.438424 + timer_stop => 1624846495.438591 status => true - pid => 350135 ] ``` diff --git a/bin/docket-cronwp.phar b/bin/docket-cronwp.phar index 5e320b1..f8292d4 100755 Binary files a/bin/docket-cronwp.phar and b/bin/docket-cronwp.phar differ diff --git a/docket-cronwp.php b/docket-cronwp.php index 8345178..94dde4f 100644 --- a/docket-cronwp.php +++ b/docket-cronwp.php @@ -16,7 +16,7 @@ \defined('DOCKET_CRONWP') && exit; -\define('DOCKET_CRONWP_VERSION', '1.0.4'); +\define('DOCKET_CRONWP_VERSION', '1.0.5'); \define('DOCKET_CRONWP_DIR', __DIR__); \define('DOCKET_CRONWP', !empty($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : __FILE__); require __DIR__.'/includes/load.php'; diff --git a/includes/src/Bepart.php b/includes/src/Bepart.php new file mode 100644 index 0000000..b5c53fe --- /dev/null +++ b/includes/src/Bepart.php @@ -0,0 +1,69 @@ +\s$/'], [null, ']$1', ' => ['], $data_r); + $data = implode(\PHP_EOL, array_filter(['['] + $data_r)); + + return str_replace([',', "'"], '', $data); + } + + private function output($text, $is_error = false) + { + $fd = $is_error ? \STDERR : \STDOUT; + fwrite($fd, $text); + } + + private function get_hash($string) + { + return substr(md5($string), 0, 12); + } + + private function lockpath() + { + return $this->normalize_path(sys_get_temp_dir().'/'); + } +} diff --git a/includes/src/Console.php b/includes/src/Console.php index 0f355c1..137a3a6 100644 --- a/includes/src/Console.php +++ b/includes/src/Console.php @@ -12,14 +12,18 @@ \defined('DOCKET_CRONWP') || exit; -final class Console extends Parser +final class Console { + use Bepart; + use Parser; + use Process; + private $pids = []; private $key; private $args = [ 'dcdir' => '', 'wpdir' => '', - 'job' => 5, + 'job' => 3, 'quiet' => false, 'dryrun' => false, 'network' => false, @@ -50,33 +54,6 @@ private function compat_notice() } } - private function normalize_path($path) - { - $wrapper = ''; - $scheme_separator = strpos($path, '://'); - if (false !== $scheme_separator) { - $stream = substr($path, 0, $scheme_separator); - if (\in_array($stream, stream_get_wrappers(), true)) { - list($wrapper, $path) = explode('://', $path, 2); - $wrapper .= '://'; - } - } - - $path = str_replace('\\', '/', $path); - $path = preg_replace('|(?<=.)/+|', '/', $path); - if (':' === substr($path, 1, 1)) { - $path = ucfirst($path); - } - - return $wrapper.$path; - } - - private function output($text, $is_error = false) - { - $fd = $is_error ? \STDERR : \STDOUT; - fwrite($fd, $text); - } - private function register_wpdir($params) { $wpdir = ''; @@ -205,114 +182,6 @@ private function register_args() } } - private function strip_proto($url) - { - return preg_replace('@^https?://@', '', $url); - } - - private function proc_store($key, $hook, $data) - { - $file = sys_get_temp_dir().'/'.$this->key.'-'.substr(md5($hook), 0, 12).'.php'; - - if (empty($data) || !\is_array($data)) { - return false; - } - - $code = 'key.'-'.substr(md5($hook), 0, 12).'.php'; - if (empty($file) || !is_file($file)) { - return false; - } - - $data = include $file; - unlink($file); - if (!empty($data) && \is_array($data)) { - return $data; - } - - return false; - } - - private function proc_fork($name, $callback) - { - if (!\is_callable($callback)) { - $this->output($callback.' is not callable'.\PHP_EOL, true); - - return false; - } - - $pid = pcntl_fork(); - if (-1 === $pid) { - $this->output('Failed to fork the cron event '.$name.\PHP_EOL); - - return false; - } - if ($pid) { - $this->pids[$name] = $pid; - - return true; - } - \call_user_func($callback); - exit(0); - } - - private function result_export($data) - { - $data_e = var_export($data, true); - $data_e = str_replace('Requests_Utility_CaseInsensitiveDictionary::__set_state(', '', $data_e); - - $data_e = preg_replace('/^([ ]*)(.*)/m', '$1$1$2', $data_e); - $data_r = preg_split("/\r\n|\n|\r/", $data_e); - - $data_r = preg_replace(['/\s*array\s\($/', '/\)(,)?$/', '/\s=>\s$/'], [null, ']$1', ' => ['], $data_r); - $data = implode(\PHP_EOL, array_filter(['['] + $data_r)); - - return str_replace([',', "'"], '', $data); - } - - private function proc_wait() - { - if (empty($this->pids)) { - return false; - } - - $pids = array_keys($this->pids); - foreach ($pids as $key) { - if (!isset($this->pids[$key])) { - continue; - } - - $pid = pcntl_waitpid($this->pids[$key], $status); - if (-1 === $pid || $pid > 0) { - unset($this->pids[$key]); - } - - $result = $this->proc_get($this->key, $key); - - 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); - } - - $result['pid'] = $pid; - $this->output($this->result_export($result).\PHP_EOL.\PHP_EOL); - } - - return $this->pids; - } - private function register_wpload() { if (!isset($_SERVER['HTTP_HOST'])) { @@ -341,9 +210,9 @@ private function register_wpload() public function run() { $site = $this->strip_proto(get_home_url()); - $this->key = 'dcronwp-'.substr(md5($site), 0, 12); + $this->key = 'dcronwp-'.$this->get_hash($site); - $lock_file = sys_get_temp_dir().'/'.$this->key.'-data.php'; + $lock_file = $this->lockpath().$this->key.'-data.php'; $stmp = time() + 120; if (is_file($lock_file) && is_writable($lock_file) && $stmp > @filemtime($lock_file)) { @@ -411,23 +280,35 @@ function ($lockfile) use ($lock_file) { $hook, function () use ($hook, $args) { if (!$this->args['dryrun']) { - $timer_start = sprintf('%.3F', microtime(true)); + $timer_start = microtime(true); $status = true; $error = ''; + $content = ''; + $atime = date('Y-m-d H:i:s'); try { + ob_start(); do_action_ref_array($hook, $args); + $content = ob_get_contents(); + ob_end_clean(); } catch (\Throwable $e) { $status = false; $error = $e->getMessage(); } - $timer_stop = sprintf('%.3F', microtime(true)); + $timer_stop = microtime(true); $data = [ + 'pid' => '', + 'time' => $atime, 'hook' => $hook, 'timer_start' => $timer_start, 'timer_stop' => $timer_stop, 'status' => $status, ]; + + if ('' !== $content) { + $data['output'] = trim($content); + } + if (!$status && !empty($error)) { $data['error'] = $error; } diff --git a/includes/src/Parser.php b/includes/src/Parser.php index 389d190..c01d928 100644 --- a/includes/src/Parser.php +++ b/includes/src/Parser.php @@ -18,7 +18,7 @@ \defined('DOCKET_CRONWP') || exit; -class Parser +trait Parser { private $boolParamSet = [ 'y' => true, diff --git a/includes/src/Process.php b/includes/src/Process.php new file mode 100644 index 0000000..a00135d --- /dev/null +++ b/includes/src/Process.php @@ -0,0 +1,105 @@ +lockpath().$this->key.'-'.$this->get_hash($hook).'.php'; + + if (empty($data) || !\is_array($data)) { + return false; + } + + $code = 'lockpath().$this->key.'-'.$this->get_hash($hook).'.php'; + if (empty($file) || !is_file($file)) { + return false; + } + + $data = include $file; + unlink($file); + if (!empty($data) && \is_array($data)) { + return $data; + } + + return false; + } + + private function proc_fork($name, $callback) + { + if (!\is_callable($callback)) { + $this->output($callback.' is not callable'.\PHP_EOL, true); + + return false; + } + + $pid = pcntl_fork(); + if (-1 === $pid) { + $this->output('Failed to fork the cron event '.$name.\PHP_EOL); + + return false; + } + if ($pid) { + $this->pids[$name] = $pid; + + return true; + } + \call_user_func($callback); + exit(0); + } + + private function proc_wait() + { + if (empty($this->pids)) { + return false; + } + + $pids = array_keys($this->pids); + foreach ($pids as $key) { + if (!isset($this->pids[$key])) { + continue; + } + + $pid = pcntl_waitpid($this->pids[$key], $status); + if (-1 === $pid || $pid > 0) { + unset($this->pids[$key]); + } + + $result = $this->proc_get($this->key, $key); + 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); + $result['pid'] = $pid; + $this->output($this->result_export($result).\PHP_EOL.\PHP_EOL); + } + } + } + + return $this->pids; + } +} diff --git a/includes/vendor/composer/InstalledVersions.php b/includes/vendor/composer/InstalledVersions.php index 098e39b..969fe11 100644 --- a/includes/vendor/composer/InstalledVersions.php +++ b/includes/vendor/composer/InstalledVersions.php @@ -29,7 +29,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => '1123646a648adb7b9e0787d3fdc6668c2a9b5f4a', + 'reference' => '44fb94c05acfeec32101b20475906cd14c245893', 'name' => 'nawawi/docket-cronwp', ), 'versions' => @@ -41,7 +41,7 @@ class InstalledVersions 'aliases' => array ( ), - 'reference' => '1123646a648adb7b9e0787d3fdc6668c2a9b5f4a', + 'reference' => '44fb94c05acfeec32101b20475906cd14c245893', ), ), ); diff --git a/includes/vendor/composer/autoload_classmap.php b/includes/vendor/composer/autoload_classmap.php index 3eadc25..428db72 100644 --- a/includes/vendor/composer/autoload_classmap.php +++ b/includes/vendor/composer/autoload_classmap.php @@ -7,6 +7,8 @@ return array( 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', + 'Nawawi\\DocketCronWP\\Bepart' => $baseDir . '/includes/src/Bepart.php', 'Nawawi\\DocketCronWP\\Console' => $baseDir . '/includes/src/Console.php', 'Nawawi\\DocketCronWP\\Parser' => $baseDir . '/includes/src/Parser.php', + 'Nawawi\\DocketCronWP\\Process' => $baseDir . '/includes/src/Process.php', ); diff --git a/includes/vendor/composer/autoload_static.php b/includes/vendor/composer/autoload_static.php index a2e829d..93bcc5b 100644 --- a/includes/vendor/composer/autoload_static.php +++ b/includes/vendor/composer/autoload_static.php @@ -22,8 +22,10 @@ class ComposerStaticInit1d00991b6227419f508f6e3679679277 public static $classMap = array ( 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + 'Nawawi\\DocketCronWP\\Bepart' => __DIR__ . '/../../..' . '/includes/src/Bepart.php', 'Nawawi\\DocketCronWP\\Console' => __DIR__ . '/../../..' . '/includes/src/Console.php', 'Nawawi\\DocketCronWP\\Parser' => __DIR__ . '/../../..' . '/includes/src/Parser.php', + 'Nawawi\\DocketCronWP\\Process' => __DIR__ . '/../../..' . '/includes/src/Process.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/includes/vendor/composer/installed.php b/includes/vendor/composer/installed.php index 0bd954e..5404758 100644 --- a/includes/vendor/composer/installed.php +++ b/includes/vendor/composer/installed.php @@ -6,7 +6,7 @@ 'aliases' => array ( ), - 'reference' => '1123646a648adb7b9e0787d3fdc6668c2a9b5f4a', + 'reference' => '44fb94c05acfeec32101b20475906cd14c245893', 'name' => 'nawawi/docket-cronwp', ), 'versions' => @@ -18,7 +18,7 @@ 'aliases' => array ( ), - 'reference' => '1123646a648adb7b9e0787d3fdc6668c2a9b5f4a', + 'reference' => '44fb94c05acfeec32101b20475906cd14c245893', ), ), );