kelemen/parallel
Composer 安装命令:
composer require kelemen/parallel
包简介
Library for parallel running tasks
关键字:
README 文档
README
Library for parallel (concurrent) task processing. Implemented with symfony/process.
Basic table output
Configuration
Basic
command.php
#!/usr/bin/env php <?php require_once __DIR__ . '/../vendor/autoload.php'; // First setup Parallel class // If you setup log dir (optional) parallel will automatically create sub folder /stats and log running statistics in json format here. $parallel = new \Parallel\Parallel(__DIR__, 'parallel', 5, 0.1); // Add some tasks (only examples, not part of parallel) // Task is defined by its name and by dependencies (optional) // Dependencies ($runAfter = []) are tasks which have to be done before task can start $parallel->addTask(new \Parallel\AdminsTask('task:admin'), ['task:categories']); $parallel->addTask(new \Parallel\UsersTask('task:user')); $parallel->addTask(new \Parallel\ArticlesTask('task:articles'), ['task:admin', 'task:user']); $parallel->addTask(new \Parallel\CategoriesTask('task:categories')); // Some tasks can be too much resource expensive, so we can define how many tasks can run along this task. // If we setup 0, this task will be run alone although we setup 5 as global max concurrent $parallel->addTask(new \Parallel\ArticleCategoriesTask('task:articlesCategories'), 0); // Run symfony application under hood $parallel->runConsoleApp();
Now simply run
php command.php parallel:run
Run only subnet of registered tasks
Sometimes you want to run only subnet of registered task (eg. in development). For this purpose use --subnet option in parallel:run command.
--subnet option is validated as regexp and accept multiple values. Also all dependencies that doesn't match any of subnet regexp is removed from matched tasks.
# This command run only task:user and task:categories tasks
php command.php parallel:run --subnet task:user$ --subnet task:categories$
Logging
PSR logger is implemented. So we can use monolog/monolog.
<?php // Setup PSR logger // ... $parallel->setLogger($psrLogger);
Analyze command
Parallel can visualize tasks dependencies graph. All you have to do is set analyze dir. Output file in HTML format will be generated to setup directory.
<?php $parallel->setAnalyzeDir(__DIR__ . '/../log');
# Now you can run
php command.php analyze:graph
Tasks
Every task has to return some kind of result (SuccessResult, SkipResult, ErrorResult) as the result of task/item processing.
Task types
SimpleTask
Suitable for tasks with static input data processing.
<?php class ImplementedSimpleTask extends SimpleTask { protected function processTask(InputInterface $input, OutputInterface $output): TaskResult { // Do some magic return new SuccessResult(); } }
ProgressTask
Suitable if you need to process each item from a medium dataset separately. All source items are provided at once. In some cases it can be too expensive for memory (see BatchProgressTask).
<?php class ImplementedProgressTask extends ProgressTask { protected function items(): iterable { return DB::table('users'); } protected function itemsCount(): int { return DB::table('users')->count(); } protected function processItem($item): TaskResult { // $item here is one record form users table // It can be anything what is provided by items() method (array, object ...) if (!$item['is_active']) { return new SkipResult(); } file_put_contents('active_users', $item['id'] . "/n", FILE_APPEND | LOCK_EX); return SuccessResult(); } }
BatchProgressTask
Most advanced task. Suitable if you need to process each item from a large dataset separately. Items can be provided and processed in batches.
<?php class ImplementedBatchProgressTask extends BatchProgressTask { protected function startup(): void { // Here you can prepare data } protected function shutdown(): void { // Here you can run cleanup } protected function items(int $processed): iterable { // Fetch data (eg. from database) by 500 and use offset return DB::table('users')->limit(500)->offset($processed); } protected function itemsCount(): int { // Count ALL data that will be processed return DB::table('users')->count(); } protected function processItem($item): TaskResult { // $item here is one record form users table if (!$item['is_active']) { return new SkipResult(); } return new SuccessResult([ 'id' => $item['id'], 'name' => $item['name'] ]); } protected function batch(array $items): void { DB::table('active_users')->insert($items); } }
Messages
Anywhere in ProgressTask and BatchProgressTask can be send message to output with sendMessage($message) method.
TaskGenerator
The TaskGenerator interface in the Parallel library allows you to dynamically generate tasks. This is useful when you need to create tasks based on criteria or input data that may not be known beforehand.
Creating a New TaskGenerator
To create a new TaskGenerator, implement the TaskGenerator interface. This interface requires the implementation of two methods: getName and generateTasks.
Here's an example of how to create a new TaskGenerator:
namespace Parallel\TaskGenerator; use Parallel\Task; class CustomTaskGenerator implements TaskGenerator { private $name; private $task; private $runAfter = []; private $maxConcurrentTasksCount; private $chunkSize; public function __construct(string $name, Task $task, int $chunksCount, array $runAfter = [], ?int $maxConcurrentTasksCount = null) { $this->name = $name; $this->task = $task; $this->chunkSize = $chunksCount; $this->runAfter = $runAfter; $this->maxConcurrentTasksCount = $maxConcurrentTasksCount; } public function getName(): string { return $this->name; } public function generateTasks(): array { $tasks = []; for ($i = 1; $i <= $this->chunkSize; $i++) { $tasks[] = new BaseGeneratedTask($this->task, $this->runAfter, $this->maxConcurrentTasksCount); } return $tasks; } }
Adding TaskGenerators to Parallel
Once you have created your TaskGenerator, add it to the Parallel instance. This allows the dynamically generated tasks to be included in the parallel processing.
$taskGenerator = new CustomTaskGenerator('custom', new \Parallel\SomeTask('task:custom'), 10, ['task:dependency'], 2); $parallel->addTaskGenerator($taskGenerator);
Working with Generated Tasks
Tasks generated by a TaskGenerator can have dependencies just like regular tasks. Specify these dependencies when creating the generated tasks. The Parallel library ensures these tasks are executed in the correct order.
public function generateTasks(): array { $tasks = []; for ($i = 1; $i <= $this->chunkSize; $i++) { $tasks[] = new BaseGeneratedTask($this->task, ['task:dependency'], $this->maxConcurrentTasksCount); } return $tasks; }
In this example, each generated task depends on task:dependency.
Setting Dependencies for Tasks That Run After Generated Tasks
To set dependencies for tasks that should run after the tasks generated by a TaskGenerator, reference the generator's name. This ensures that the task will wait for all tasks generated by the generator to complete before it starts.
$parallel->addTask(new \Parallel\SomeOtherTask('task:afterGenerated'), ['custom']);
In this example, task:afterGenerated will only start after all tasks generated by the CustomTaskGenerator (named custom) have finished.
afterGenerated` will only start after all tasks generated by CustomTaskGenerator have finished.
kelemen/parallel 适用场景与选型建议
kelemen/parallel 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 19.88k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2017 年 04 月 26 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「imports」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 kelemen/parallel 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 kelemen/parallel 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 kelemen/parallel 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Workflow Configuration UI for Pimcore
Data Definitions allows you to define your DataObject Imports and Exports using a nice GUI and re-run the definitions as often you like.
Parallel task logger DB implementation
Workflow Configuration UI for Pimcore
Streamline excel data import to your application
A small class to help clean headings on an imported CSV file to make them more understandable
统计信息
- 总下载量: 19.88k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 2
- 点击次数: 13
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2017-04-26
