3.5. 事件
这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。
请对照 原文链接 进行翻译
EVENTS
Rocketeer is at its core driven by Tasks. Each of these tasks has a whole ecosystem of events fired in their lifetime, powered by the illuminate/events components. Therefor, when you're doing this :
Rocketeer::before('deploy', 'MyApp\MyCustomTask');
What you're actually doing is, more simply put :
$app['events']->listen('rocketeer.deploy.before', 'MyApp\MyCustomTask@execute');
This is not "just this" of course, as Rocketeer does some magic on the second argument so that Rocketeer::before('deploy', 'composer install')
transforms composer install
into an actual Task class the Events Dispatcher can call. But in its concept, it's just your basic Dispatcher (or Observer if you like) system.
Registering events
First of all, you can register events in any file that is autoloaded by Composer. If you're using the Rocketeer archive and have no particular autoloading, Rocketeer will by default try to load .rocketeer/events.php
or if you have more events and want to split them in multiple files, it'll autoload every file in a .rocketeer/events/*
folder.
Listening to events
All tasks in Rocketeer fire two basic events : before
and after
on which you can hook. But some tasks fire internal events, during their execution, allowing you to execute actions at various points in their lifetime. To listen to these events, there are two methods you can use. Say you want to execute something before the Deploy task symlinks the current
folder to the latest release :
Rocketeer::addTaskListeners('deploy', 'before-symlink', function ($task) {
echo $task->releasesManager->getCurrentRelease();
});
// Or
Rocketeer::listenTo('deploy.before-symlink', function ($task) {
echo $task->releasesManager->getCurrentRelease();
});
These two methods look very similar but in appearance only, the first one actually calls the second but allows you to pass an array of tasks names or instances :
Rocketeer::addTaskListeners(['deploy', new Rocketeer\Tasks\Setup], 'some-event', function ($task) {
echo $task->releasesManager->getCurrentRelease();
});
Firing events in your own tasks
You can fire events in your own tasks too by using the fireEvent
method :
class MyTask extends Rocketeer\Abstracts\AbstractTask
{
public function execute()
{
$this->fireEvent('making-coffee');
$this->makeCoffee();
$this->fireEvent('drinking-coffee');
$this->drinkCoffee();
}
}
You don't need to namespace your events, as Rocketeer will do it for you. It will first namespace all events in the rocketeer.
space, then add a slug of the current task, so the two events above would be fired as rocketeer.my-task.making-coffee
and rocketeer.my-task.drinking-coffee
:
Rocketeer::listenTo('my-task.drinking-coffee', 'ls');
Now, you can also fire events in Closure Tasks, by you will need to manually namespace those : as all Closure Tasks are at their core anonymous functions, they're anonymous tasks as well which means all events will get fired in rocketeer.closure
:
Rocketeer::after('deploy', function ($task) {
$task->fireEvent('some-event'); // Will get fired as rocketeer.closure.some-event
});
This is not a problem per se but can get problematic if you have a lot of Closure Tasks.
Firing events in a particular order
As the events system use illuminate/events
, it inherits its priority methods. That means that for every method that adds listeners to an event, you can specify a priority for these listeners. Simple example :
Rocketeer::after('deploy', function ($task) {
$task->campfire->notify('New version deployed on the server');
});
Rocketeer::after('deploy', ['npm install', 'grunt']);
Now ideally you'd want your chat room on Campfire to be notified about the deployment only when the NPM packages are installed and Grunt has run its course, because an error might happen there. For this you add a priority at the end of the call : priority is a basic integer, listeners with lowest priority will be fired at the end, and vice versa. So to make sure our Campfire notification would get sent at really the very end of all our listeners, we can just do this :
Rocketeer::after('deploy', function ($task) {
$task->campfire->notify('New version deployed on the server');
}, -10);
Rocketeer::after('deploy', function ($task) {
$task->runForCurrentRelease(['npm install', 'grunt']);
});
Here are some methods that accept a priority argument :
Rocketeer::before($task, $listeners, $priority = 0)
Rocketeer::after($task, $listeners, $priority = 0)
Rocketeer::listenTo($event, $listeners, $priority = 0)
Rocketeer::addTaskListeners($tasks, $event, $listeners, $priority = 0)
Halting the queue in an event
Whenever an event returns a strict false
, Rocketeer will recognize it and halt the whole queue. This is useful to do checks before certain major events and cancel per example deployment if some conditions are not met.
To halt the queue you can either simply return false :
Rocketeer::before('deploy', function ($task) {
if (!$something) {
return false;
}
});
Or if you want to pass additional details, you can use the Task::halt
method which will display as error whatever you pass to it, and then return false :
Rocketeer::before('deploy', function ($task) {
if (!$something) {
return $this->halt('Something was wrong here, cancelling');
}
});
Whatever you use, Rocketeer will display an additional error message stating the queue was canceled and by what Task.
可用事件
默认情况下,所有任务都有 before
和 after
事件,所有策略也是如此。 例如,Deploy
任务将分别调用以下策略: CreateRelease
,Dependencies
,Test
和 Migrate
。 这意味着在部署的情况下,可以将自己挂在以下事件上:
deploy.before
create-release.before
create-release.after
dependencies.before
dependencies.after
test.before
test.after
migrate.before
migrate.after
deploy.before-symlink
deploy.after
请注意 deploy.before-symlink
事件,它是一个特殊事件,在版本被符号链接为当前版本之前触发。 这是在发布上线之前,对其进行任何工作的推荐位置。
故障事件
所有任务在失败时也会触发 halt
事件,无论它是来自自身、绑定事件还是子任务。 你可以像其他任何事件一样连接到这些事件。
例如,如果你有一个数据库备份系统,你希望在部署迁移失败时,恢复该数据库备份,那么可以执行以下操作:
Rocketeer::listenTo('migrate.halt', function() {
// 恢复数据库
});
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。