翻译进度
4
分块数量
1
参与人数

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.

可用事件

默认情况下,所有任务都有 beforeafter 事件,所有策略也是如此。 例如,Deploy 任务将分别调用以下策略: CreateReleaseDependencies,TestMigrate。 这意味着在部署的情况下,可以将自己挂在以下事件上:

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() {
  // 恢复数据库
});
郁雁 翻译于 3年前

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

thebestxt
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~