Skip to content

Commit

Permalink
Issue #3: Refactored background processing into autoloaded worker class.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ambient-Impact committed Jul 15, 2023
1 parent d3210e9 commit 51d7c35
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 42 deletions.
52 changes: 10 additions & 42 deletions .do/run-background-tasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,43 @@

declare(strict_types=1);

use React\ChildProcess\Process;
use Omnipedia\BackgroundTasks\WorkerProcess;
use React\EventLoop\Loop;

require __DIR__ . '/../vendor/autoload.php';

function worker_process(string $command): void {

print 'Running: ' . $command . \PHP_EOL;

$process = new Process($command);

$process->start();

$process->on('exit', function(
?int $exitCode, $termSignal
) use ($command): void {
if ($exitCode === null) {
print "Command '$command' terminated with signal: $termSignal";
}
// print 'Process exited with code ' . $exitCode . \PHP_EOL;
});
$process->stdout->on('data', function($chunk): void {
print $chunk;
});
$process->stderr->on('data', function($chunk) use ($command): void {
if (!empty(trim($chunk))) {
print $chunk;
}
});
// $process->stdout->on('error', function(\Exception $exception) use ($command): void {
// print 'Error: ' . $exception->getMessage();
// });
// $process->stderr->on('error', function(\Exception $exception) use ($command): void {
// print 'Error: ' . $exception->getMessage();
// });

}

$drush = __DIR__ . '/../vendor/bin/drush';
$drush = \realpath(__DIR__ . '/../vendor/bin/drush');

/** @var \React\EventLoop\LoopInterface */
$loop = Loop::get();

// Run common tasks immediately.
$loop->futureTick(function() {
\worker_process(__DIR__ . '/run-common.sh');
(new WorkerProcess(__DIR__ . '/run-common.sh'))->start();
});

// Run cron every 15 minutes.
$loop->addPeriodicTimer(900, function() use ($drush): void {
\worker_process($drush . ' cron');
(new WorkerProcess($drush . ' cron'))->start();
});

// Every 5 minutes, process jobs from the image style warmer.
$loop->addPeriodicTimer(300, function() use ($drush): void {
\worker_process(
(new WorkerProcess(
$drush . ' queue:run image_style_warmer_pregenerator --verbose'
);
))->start();
});

// Every 10 minutes, process the wiki page changes queue.
$loop->addPeriodicTimer(600, function() use ($drush): void {
\worker_process($drush . ' omnipedia:changes-build --verbose');
(new WorkerProcess($drush . ' omnipedia:changes-build --verbose'))->start();
});

// Every 10 minutes, process the wiki page CDN warmer queue.
$loop->addPeriodicTimer(600, function() use ($drush): void {
\worker_process(
(new WorkerProcess(
$drush . ' warmer:enqueue omnipedia_wiki_node_cdn --run-queue --verbose'
);
))->start();
});

$loop->run();
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@
"phpstan/extension-installer": true
}
},
"autoload": {
"psr-4": {
"Omnipedia\\" : "src/"
}
},
"extra": {
"enable-patching": true,
"composer-exit-on-patch-failure": true,
Expand Down
100 changes: 100 additions & 0 deletions src/BackgroundTasks/WorkerProcess.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php

declare(strict_types=1);

namespace Omnipedia\BackgroundTasks;

use React\ChildProcess\Process;

/**
* Omnipedia background tasks worker process wrapper.
*/
class WorkerProcess {

/**
* The ReactPHP Process instance for this command.
*
* @var \React\ChildProcess\Process
*/
protected Process $process;

/**
* Constructor; instantiates a new ReactPHP Process.
*
* @param string $command
* Command to run.
*/
public function __construct(string $command) {

$this->process = new Process($command);

}

/**
* Start the configured process.
*/
public function start(): void {

print 'Running: ' . $this->process->getCommand() . \PHP_EOL;

$this->process->start();

$this->process->on('exit', [$this, 'onProcessExit']);

$this->process->stdout->on('data', [$this, 'onStdOutData']);

$this->process->stderr->on('data', [$this, 'onStdErrData']);

}

/**
* Process exit event handler.
*
* @param int|null $exitCode
*
* @param int|null $termSignal
*/
public function onProcessExit(?int $exitCode, ?int $termSignal): void {

if ($exitCode !== null) {
return;
}

print \sprintf(
'Command %s terminated with signal: %s',
$this->process->getCommand(), $termSignal
);

}

/**
* stdout data event handler; prints output.
*
* @param string $chunk
* Output data string/chunk. In other contexts this can also be binary data,
* but in our case we're only expecting a string.
*/
public function onStdOutData(string $chunk): void {

print $chunk;

}

/**
* stderr data event handler; prints output.
*
* @param string $chunk
* Output data string/chunk. In other contexts this can also be binary data,
* but in our case we're only expecting a string.
*/
public function onStdErrData(string $chunk): void {

if (empty(trim($chunk))) {
return;
}

print $chunk;

}

}

0 comments on commit 51d7c35

Please sign in to comment.