trntv / yii2-command-bus Goto Github PK
View Code? Open in Web Editor NEWCommand Bus for Yii2
License: BSD 3-Clause "New" or "Revised" License
Command Bus for Yii2
License: BSD 3-Clause "New" or "Revised" License
I needed to run 3 background commands in async mode and then wait in controller for all of them to finish
So far I found example of running in serially / parallely but how can we wait for two or more parallel commands in controller ?
Hello,
Thanks for this command bus. I'm Trying to use the following syntax:
Yii::$app->commandBus->locator->addHandler('app\handlers\SomeHandler', 'app\commands\SomeCommand');
And I've got that error:
Error: Argument 1 passed to trntv\bus\locators\ClassNameLocator::addHandler() must be an instance of trntv\bus\interfaces\Handler, string given
It seems to be due by the type define in function declaration in ClassNameLocator.php#L43
public function addHandler(Handler $handler, $className)
Should remove the Handler
type or remove the line in documentation. Or am I mistaken on the way to use the syntax ?
Regards,
Hi i am testing out your extension yii2-command-bus.
So far everything works fine.
On the first tests I thought that I don't have to wait for the process when using Background commands with symfony but the Queued fulfilled my requirement to execute external code independent on the page rendered.
I wanted to sent e.g. 1000 email via a background process.
The process is now running with your command bus extension and an queued Command like this:
class SendQueuedEmailsCommand extends Object implements SelfHandlingCommand, QueuedCommand
My question regarding your extension are:
If you have an example how to log the job status and result with your extension I would really appreciate this.
Can you fix this issue?
i really got puzzled...
QueueBusController.php
in loop method, change to this:
if($job)
{
blabala...
}
I'm running PHP-FPM on my server, so when I try and use this commandbus library with the background async process it never actually runs anything because the PHP_BINARY is set to "php-fpm" and php doesn't run commands on that. Any ideas?
Здравствуйте. Решил попробовать использовать ваше расширение и получилось так, что оно не запускает команды в фоне.
Конфигурация:
'controllerMap' => [
...
'background-bus' => [
'class' => 'trntv\bus\console\BackgroundBusController',
]
],
'components' => [
...
'commandBus' => [
'class' => 'trntv\bus\CommandBus',
'middlewares' => [
[
'class' => '\trntv\bus\middlewares\BackgroundCommandMiddleware',
'backgroundHandlerBinary' => '/usr/bin/php',
'backgroundHandlerPath' => '@app/../yii',
'backgroundHandlerRoute' => 'background-bus/handle',
],
[
'class' => '\trntv\bus\middlewares\LoggingMiddleware',
'level' => 1,
],
],
],
],
Команда:
<?php
namespace app\commands\handles;
use trntv\bus\middlewares\BackgroundCommandTrait;
use trntv\bus\interfaces\BackgroundCommand;
use trntv\bus\interfaces\SelfHandlingCommand;
use yii\base\Object;
use Yii;
class TestCommand extends Object implements BackgroundCommand, SelfHandlingCommand
{
use BackgroundCommandTrait;
public $setTo;
public $subject;
public $view;
public $data;
/**
* @param $command
*/
public function handle($command)
{
for($i = 0; $i <= 100000000; $i++) {
}
// sleep(5);
echo 'test';
/*$mail = Yii::$app->getMailer();
$mail->compose($this->view, [])
->setTo($this->setTo)
->setSubject($this->subject)
->send();*/
}
}
Запуск
Yii::$app->commandBus->handle(new \app\commands\handles\TestCommand([
'setTo' => '[email protected]',
'subject' => 'Тест',
'view' => 'test',
'data' => []
]));
Смысл заключается в том, что мы должны передать данные шине, а та в свою очередь в фоновом режиме запустить консольную команду, которая выполнит необходимые действия.
Профит в том, что команда может выполняется несколько секунд, а для пользователя все будет мгновенно. Классический пример отправка почтового сообщения.
С текущей конфигурацией и кодом ошибок не возникает, все отрабатывает корректно, за исключением того, что сама команда выполняется не в фоне. Тоесть идет загрузка на протяжении нескольких секунд пока не отработает цикл или sleep.
I have configure background command process as per your docs.
'middlewares' => [
[
'class' => '\trntv\bus\middlewares\BackgroundCommandMiddleware',
'backgroundHandlerPath' => '@app/yii',
'backgroundHandlerRoute' => 'background-bus/handle',
]
]
But not given details description of background-bus/handle
.
Please give me which code is required in handle
method or give reference.
replace Object to BaseObject
Hi trntv
as mentioned in #12 id had issues with the log in queued background commands. The log was either only flushed after the default exportInterval of 1000.
And you have fixed it.
But this is still not working correctly or to be correct only works if the log target has set it´s exportInterval
to 1
to export after each log.
Otherwise it also won't be exported directly.
I would prefer a function in the LoggingMiddleware which does the log and flush with final = true
public function log($message, $level = null, $category = null)
{
// set default level if level isn't set
if (!$level) {
$level = $this->level;
}
// set default category if level isn't set
if (!$category) {
$category = $this->category;
}
// log
$this->logger->log($message, $level, $category);
// force with final = true so export is done afterwards
if ($this->forceFlush) {
$this->logger->flush($final = true);
}
}
public function execute($command, callable $next)
{
$class = get_class($command);
$this->log("Command execution started: {$class}", Logger::LEVEL_INFO);
$result = $next($command);
$this->log("Command execution ended: {$class}", Logger::LEVEL_INFO);
return $result;
}
With this code the log is done directly if forceFlush is set to true.
So at the start and end of a command the log is correctly exported.
My only problem is now I also wanted to have the log mechanism inside of the command.
I wanted to create a "live-log" to see which emails are already been sent out.
It would be cool if the running command could somehow call
$this->log("whatever")
and it is automatically also exported to the log with the correct category through the LoggingMiddleware.
This was also why I have created a log function in the middleware.
Is it somehow possible to get to the LoggingMiddleware object from the Command and use the log function?
Also if I wanted to get all information of e.g. occurred errors of the QueueBusController those errors are only logged to the console output.
e.g. on actionListen
console::error
is used instead of log also to the Yii logger with Yii::error
.
As far as i see it is also not possible to pause
or abort
a running background command by setting some flags.
Do you remember this issue #5 ?
There I wanted to log the onError, onSuccess etc. messages.
I still have the problem if my comand does this
Yii::error('I am an error', 'command-bus');
return false;
The console still outputs
Listening queue "some-queue-name"
New job ID#71
Job ID#71 was deleted from queue
Job ID#71 has been successfully done
and my Log from my LogginMiddleware
2016-09-08 15:20:54 [console][][info][command-bus] Command execution started: common\commands\SendQueuedEmailsCommand
2016-09-08 15:20:54 [console][][error][command-bus] i am an error
2016-09-08 15:20:54 [console][][info][command-bus] Command execution ended: common\commands\SendQueuedEmailsCommand
So I won't see that there was an error in my command "return was false"
in the log created by LogginMiddleware.
And what`s more problematic if somehow a exception is throwed in the QueuedCommand (or the functions called) the command will be running in a loop and won't stop.
Just call in an QueuedCommand
throw new Exception("Error Processing Request", 1);
And the process not ended or the command aborted.
I guess this is some issue in the CommandBus::createMiddlewareChain and could be fixed like below.
protected function createMiddlewareChain($command, array $middlewareList) {
$lastCallable = $this->createHandlerCallable($command);
while ($middleware = array_pop($middlewareList)) {
if (!$middleware instanceof Middleware) {
throw new InvalidConfigException;
}
$lastCallable = function ($command) use ($middleware, $lastCallable) {
try {
return $middleware->execute($command, $lastCallable);
} catch (\Exception $e) {
yii\helpers\Console::error("Exception: ".$e->getMessage());
Yii::error("Exception: ".$e->getMessage(), 'command-bus');
Yii::getLogger()->flush($final = true);
}
//return $middleware->execute($command, $lastCallable);
};
}
return $lastCallable;
}
Also here it would be better if the LogginMiddleware could be called directly to directly flush the error message to the logs.
So why could the commandbus not log directly so he could log the on start/end/error/abort directly and the command should also be able to call this log function somehow through a reference to the commandbus.
Hi there is a problem with the logging mechanism in combination with QueuedCommandMiddleware.
The problem is the default Logger has a flush Interval of 1000.
http://www.yiiframework.com/doc-2.0/yii-log-logger.html#$flushInterval-detail
So only after 1000 logs logs like
Yii::getLogger()->log("Command execution started: {$class}", $this->level, $this->category);"
would be written to the log when a QueuedCommandMiddleware is used. Because the Process doesn't stop so the logger isn't flushed at the end.
Also there should be mentioned that if you want a logging mechanism almost realtime you also have to set the 'exportInterval' => 1,
in your log target.
http://www.yiiframework.com/doc-2.0/yii-log-target.html#$exportInterval-detail
Otherwise also after 1000 log messages the log would be really written.
There should also be a flush added after each Logger::log call in the LoggingMiddleware.
Hi,
I follow the readme "2. Background commands support (optional)"
ReportCommand:
`class ReportCommand extends Object implements BackgroundCommand, SelfHandlingCommand
{
use BackgroundCommandTrait;
public $someImportantData;
public function handle($command) {
// do what you need
// echo 'handle command';
$m = new TimelineEvent();
$m->application = 'application';
$m->category = 'test';
$m->event = 'test';
$m->data = json_encode(['k'=>'v'], JSON_UNESCAPED_UNICODE);
$r = $m->save(false);
return $r;
}
}`
Controller:
$process = Yii::$app->commandBus->handle(new ReportCommand([ 'async' => true, 'someImportantData' => [], ])); sleep(5); // Notice this line
If use sleep here, it will work(a new record in DB). If not use sleep, it will not work(I can't find new record in DB). What's the difference?
Need your help, thank you!
yii\base\ErrorException: proc_open(): unable to create pipe Too many open files in @vendor/symfony/process/Process.php:303
Hi, first of all, thank you for extension.
I use RedisQueue and self-handling commands, and they're great, BUT I need to set custom delay for some kind of commands. Now I have to temporary change $delay
property of QueueMiddleware
, and this is not great. May be we could make some kind of DelayedCommand
with getDelay()
method?
Добрый день!
Хочу использовать другую очередь заданий, нежели yii/yii2-queue.
Вот этот: https://github.com/zhuravljov/yii2-queue
Прописал свой middleware:
'middlewares' => [
[
'class' => '\common\commands\middlewares\QueuedCommandMiddleware',
]
]
Внутри middleware прописал нужные проверки класса.
Но не знаю, какой указать локатор или как сконфигурировать существующий?
**Call to a member function locate() on null**
if ($command instanceof SelfHandlingCommand) {
$handler = $command;
} else {
$handler = $this->locator->locate($command, $this);
}
Спасибо.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.