mwstake/mediawiki-component-processmanager

3.0.1 2024-07-19 11:03 UTC

README

此库允许您创建异步后台进程,这些进程可以从任何地方稍后访问,以检查进度和检索输出。当您启动进程时,它将被排队,并等待进程运行器执行它。

使用方法

进程基于提供给它的步骤工作,它将顺序执行步骤,将一个步骤的输出数据作为下一个步骤的输入,直到结束。最后一个步骤将返回其输出作为整个过程的输出。

步骤定义为 ObjectFactory 规范。从此类规范生成的对象必须是 MWStake\MediaWiki\Component\ProcessManager\IProcessStep 的实例。

示例步骤

class Foo implements IProcessStep {

	/** @var ILoadBalancer */
	private $lb;
	/** @var string */
	private $name;

	public function __construct( ILoadBalancer $lb, $name ) {
		$this->lb = $lb;
		$this->name = $name;
	}

	public function execute( $data = [] ): array  {
	// Add "_bar" to the name passed as the argument in the spec and return it
		$name = $this->name . '_bar';

		// some lenghty code

		return [ 'modifiedName' => $name ];
	}
}

创建进程

// Create process that has a single step, Foo, defined above
// new ManagerProcess( array $steps, int $timeout );
$process = new ManagedProcess( [
	'foo-step' => [
		'class' => Foo::class,
		'args' => [ 'Bar-name' ],
		'services' => [ 'DBLoadBalancer' ]
	]
], 300 );

$processManager = MediaWikiServices::getInstance()->getService( 'ProcessManager' );

// ProcessManager::startProcess() returns unique process ID that is required
// later on to check on the process state
echo $processManager->startProcess( $process );
// 1211a33123aae2baa6ed1d9a1846da9d

检查进程状态

一旦使用上述方法启动进程并获取进程 ID,我们就可以随时、从任何地方检查其状态,甚至从不同进程。

$processManager = MediaWikiServices::getInstance()->getService( 'ProcessManager' );
echo $processManager->getProcessInfo( $pid );
// Returns JSON
{
	"pid": "1211a33123aae2baa6ed1d9a1846da9d",
	"started_at": "20220209125814",
	"status": "finished",
	"output": { /*JSON-encoded string of whatever the last step returned as output*/ }
}

如果发生错误,响应将包含状态 error,并显示异常信息和调用堆栈。

中断进程

有时,我们希望在步骤之间暂停,并重新评估返回的数据。

如果步骤实现 MWStake\MediaWiki\Component\ProcessManager\InterruptingProcessStep 而不是 MWStake\MediaWiki\Component\ProcessManager\IProcessStep,则可以实现这一点。如果进程遇到此接口的实例,它将暂停处理并报告步骤返回的数据。

要继续进程,必须调用 $processManager->proceed($pid, $data)。在这种情况下,$pid 是暂停进程的 ID,而 $data 是要传递给下一个步骤的任何修改后的数据。此数据将与从先前步骤(暂停进程的步骤)返回的数据合并。此调用将返回进程的 PID,它应与传递的相同(同一进程继续)。

同步执行步骤

这是该组件功能的一个分支。它允许您同步执行步骤,而无需启动进程。

$executor = new \MWStake\MediaWiki\Component\ProcessManager\StepExecutor(
MediaWikiServices::getInstance()->getObjectNameUtils()
);
// Optional, if all necessary data is passed in the spec, omit this
$data = [
    'input' => 'data for the first step'
];

$executor->execute( [
    'foo-step' => [
        'class' => Foo::class,
        'args' => [
            $someArg1,
            $someArg2
        ]
    ],
    'bar-step' => [
        'class' => Bar::class,
        'args' => [
            $someArg1,
            $someArg3,
            $someArg4
        ]
    ]
], $data );

注意

  • 此组件需要一个数据库表,因此需要执行 update.php

设置

此机制具有以下主要部分

  • ProcessManager - 管理进程的服务,允许启动进程并检查其状态
  • processRunner.php - 脚本从队列检索进程并执行它们。这是一个长期运行的脚本,应作为一个后台进程启动
  • processExecution.php - 实际运行单个进程的脚本。这是一个短期脚本,仅在单个进程执行期间存在

设置 processRunner.php

脚本 processRunner.php 应由 crontab 启动。有两种操作模式

  • 执行队列中当前正在等待的进程
  • 始终运行并等待将新进程添加到队列中。这与 MediaWiki 核心中的 runJobs.php 相同。

参数

  • 第一个参数应该是 MediaWiki 核心中的 Mainetenance.php 文件的完整路径。这是由于该组件没有在代码库结构中预留专门的位置,可以安装在任何地方。
  • --wait - 等待新的进程被添加到队列中。在此模式下,脚本将创建一个锁文件,防止其他运行器启动。当你只想同时运行一个运行器时,这很有用。如果它崩溃或被其他方式终止,锁文件将被删除,其他运行器可以启动。
  • --max-jobs - 在一次运行中要执行的最大进程数。当你想限制进程数量时,这很有用。
  • --script-args - 要传递给 processExecution.php 脚本的参数。如果不清楚自己在做什么,请避免使用。

Crontab 示例:应作为 web 服务器用户或 root 执行。

* * * * * /usr/bin/php /var/www/html/mw/vendor/mwstake/mediawiki-component-processmanager/maintenance/processRunner.php /var/www/html/mw/maintenance/Maintenance.php --wait'

** 当指定 --wait 时,--max-processes 无效**

日志记录

通常,运行器将日志记录到调试日志机制的 ProcessRunner 通道中,但直接捕获脚本的输出(在 crontab 行中)并将其重定向到某个日志也很有用,这样我们就可以捕获运行器本身的任何错误。

实施中考虑的因素

这不是设置后台处理的好方法,但我们已经考虑到以下因素

  • 我们希望有一个父进程为所有进程服务,这样它们就不会变成僵尸进程,并且我们可以捕获它们的任何输出
  • 我们不希望在机器上设置任何单独的服务,如 Redis、RabbitMQ 等。理想情况下,不需要任何额外的设置,但需要 crontab 行。
  • 我们不希望等待 crontab 执行进程,我们希望能够立即启动它,因此我们有了 --wait 参数
  • 它必须在 Linux 和 Windows 上都工作