{"action":"created","comment":{"url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments/25841647","id":25841647,"diff_hunk":"@@ -13,166 +13,275 @@ var request = require('superagent-promise');\n \n var Task = require('./task');\n var EventEmitter = require('events').EventEmitter;\n+var util = require('util');\n+var TaskQueue = require('./queueservice');\n \n /**\n @param {Configuration} config for worker.\n */\n-function TaskListener(runtime) {\n-  this.runtime = runtime;\n-  EventEmitter.call(this);\n-}\n+export default class TaskListener extends EventEmitter {\n+  constructor(runtime) {\n+    this.pending = 0;\n+    this.runtime = runtime;\n+    this.capacity = runtime.capacity;\n+    this.runningTasks = [];\n+    this.taskQueue = new TaskQueue(this.runtime);\n+    this.taskPollInterval = this.runtime.taskQueue.pollInterval;\n+    this.claimConfig = {\n+      workerId: this.runtime.workerId,\n+      workerGroup: this.runtime.workerGroup\n+    };\n+    super();\n+  }\n \n-TaskListener.prototype = {\n-  __proto__: EventEmitter.prototype,\n+  listenForShutdowns() {\n+    // If node will be shutdown, stop consuming events.\n+    if (this.runtime.shutdownManager) {\n+      this.runtime.shutdownManager.once(\n+        'nodeTermination', () => {\n+          debug('nodeterm');\n+          async () => {\n+            await this.pause();\n+            for(let task of this.runningTasks) {\n+              task.abort('worker-shutdown');\n+            }\n+          }();\n+        }.bind(this)\n+      );\n+    }\n+  }\n \n-  /**\n-  Number of running tasks...\n-  */\n-  pending: 0,\n+  async cancelTask(message) {\n+    var runId = message.payload.runId;\n+    var reason = message.payload.status.runs[runId].reasonResolved;\n+    if (reason !== 'canceled') return;\n \n-  connect: function* () {\n-    this.runtime.log('listener connect');\n+    var taskId = message.payload.status.taskId;\n+    var task = this.runningTasks.find(\n+      (task) => { return (task.status.taskId === taskId && task.runId === runId); }\n+    );\n \n-    var self = this;\n-    var queue = this.runtime.queue;\n+    if (!task) debug('task not found to cancel'); return;\n \n-    // Share the queue between all workerTypes of the same provisioner.\n-    var queueName;\n-    if (this.runtime.createQueue) {\n-      queueName =\n-        QUEUE_PREFIX +\n-        this.runtime.provisionerId + '/' + this.runtime.workerType;\n-    }\n+    this.runtime.log('cancelling task', {taskId: message.payload.status.taskId});\n+    task.cancel(reason);\n+  }\n+\n+  async listenForCancelEvents() {\n+    var queue = this.runtime.queue;\n \n     var queueEvents = new taskcluster.QueueEvents();\n \n-    // Build the listener.\n-    var listener = this.listener = new taskcluster.PulseListener({\n-      prefetch:     this.runtime.capacity,\n-      credentials:  this.runtime.pulse,\n-      // Share the queue between all provisonerId + workerTypes.\n-      queueName:    queueName\n-      // TOOD: Consider adding maxLength.\n+    var cancelListener = new taskcluster.PulseListener({\n+      credentials: this.runtime.pulse\n     });\n \n-    yield listener.bind(queueEvents.taskPending({\n+    await cancelListener.bind(queueEvents.taskException({\n+      workerId: this.runtime.workerId,\n       workerType: this.runtime.workerType,\n+      workerGroup: this.runtime.workerGroup,\n       provisionerId: this.runtime.provisionerId\n     }));","path":"lib/task_listener.js","position":101,"original_position":101,"commit_id":"2e66ba69ef175fc16949bf19c01ac10b37bdfa71","original_commit_id":"2e66ba69ef175fc16949bf19c01ac10b37bdfa71","user":{"login":"jonasfj","id":149732,"avatar_url":"https://avatars.githubusercontent.com/u/149732?v=3","gravatar_id":"","url":"https://api.github.com/users/jonasfj","html_url":"https://github.com/jonasfj","followers_url":"https://api.github.com/users/jonasfj/followers","following_url":"https://api.github.com/users/jonasfj/following{/other_user}","gists_url":"https://api.github.com/users/jonasfj/gists{/gist_id}","starred_url":"https://api.github.com/users/jonasfj/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonasfj/subscriptions","organizations_url":"https://api.github.com/users/jonasfj/orgs","repos_url":"https://api.github.com/users/jonasfj/repos","events_url":"https://api.github.com/users/jonasfj/events{/privacy}","received_events_url":"https://api.github.com/users/jonasfj/received_events","type":"User","site_admin":false},"body":"We shouldn't crash on failure to keep the connection to pulse open. As we're really _only_ using it for cancel messages (which is best effort), we should listen for `cancelListener.on('error', (err) => {... });`.\r\n\r\nIdeally we could restart the connection and things, but it's a lot of work and it seems better to do this at `PulseListener` level. I want to add support for it there I just haven't figured out how to do so yet; it should probably be hidden behind a option.\r\n\r\nAnyways, IMO we should just log the error and then ignore it.. Accepting that for the rest of this docker-worker lifecycle we're not listening for taskExceptions anymore. Then we can add the reconnect option when we implement that in `PulseListener`.","created_at":"2015-03-05T06:17:04Z","updated_at":"2015-03-05T06:17:04Z","html_url":"https://github.com/taskcluster/docker-worker/pull/66#discussion_r25841647","pull_request_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66","_links":{"self":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments/25841647"},"html":{"href":"https://github.com/taskcluster/docker-worker/pull/66#discussion_r25841647"},"pull_request":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66"}}},"pull_request":{"url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66","id":30282162,"html_url":"https://github.com/taskcluster/docker-worker/pull/66","diff_url":"https://github.com/taskcluster/docker-worker/pull/66.diff","patch_url":"https://github.com/taskcluster/docker-worker/pull/66.patch","issue_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/66","number":66,"state":"open","locked":false,"title":"Spot node termination/new Worker-Queue interaction/cancellation","user":{"login":"gregarndt","id":2592630,"avatar_url":"https://avatars.githubusercontent.com/u/2592630?v=3","gravatar_id":"","url":"https://api.github.com/users/gregarndt","html_url":"https://github.com/gregarndt","followers_url":"https://api.github.com/users/gregarndt/followers","following_url":"https://api.github.com/users/gregarndt/following{/other_user}","gists_url":"https://api.github.com/users/gregarndt/gists{/gist_id}","starred_url":"https://api.github.com/users/gregarndt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregarndt/subscriptions","organizations_url":"https://api.github.com/users/gregarndt/orgs","repos_url":"https://api.github.com/users/gregarndt/repos","events_url":"https://api.github.com/users/gregarndt/events{/privacy}","received_events_url":"https://api.github.com/users/gregarndt/received_events","type":"User","site_admin":false},"body":"This PR is a combination of multiple bugs that are open for the worker that all kind of fit into each other based on the new queue rewrite:\r\nBug 1080278 - docker-worker: Listen for task-exception messages for given workerGroup and workerId \r\nBug 1110560 -  docker-worker: Report exception when spot node shutdown (clean shutdown) \r\nBug 1126648 - docker-worker: Migrate workers to the new task polling workflow\r\n\r\nAlso, at the same time some migration work has been made for 6to5/babel.  There are still pieces to convert and variable scoping changes that can be made, but this was the beginning work and if it proves to work well in production we can convert the rest with ease.\r\n\r\nThere were minor changes made to the tests to green them up because of how the queue now reports resolved states of tasks.  That accounts for 2/3rds of the files changes.\r\n\r\nNote: there were changes made and a file included for api reference so that the queue rewrite could be used locally while testing.  These changes will not make it into the final merge once the queue is deployed.\r\n\r\n\r\n","created_at":"2015-03-02T13:16:01Z","updated_at":"2015-03-05T06:17:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"08fdeb7694699ff0aa57a74b9df6e1b0857b74d2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66/commits","review_comments_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66/comments","review_comment_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments{/number}","comments_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/66/comments","statuses_url":"https://api.github.com/repos/taskcluster/docker-worker/statuses/2e66ba69ef175fc16949bf19c01ac10b37bdfa71","head":{"label":"gregarndt:spot_node_termination","ref":"spot_node_termination","sha":"2e66ba69ef175fc16949bf19c01ac10b37bdfa71","user":{"login":"gregarndt","id":2592630,"avatar_url":"https://avatars.githubusercontent.com/u/2592630?v=3","gravatar_id":"","url":"https://api.github.com/users/gregarndt","html_url":"https://github.com/gregarndt","followers_url":"https://api.github.com/users/gregarndt/followers","following_url":"https://api.github.com/users/gregarndt/following{/other_user}","gists_url":"https://api.github.com/users/gregarndt/gists{/gist_id}","starred_url":"https://api.github.com/users/gregarndt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregarndt/subscriptions","organizations_url":"https://api.github.com/users/gregarndt/orgs","repos_url":"https://api.github.com/users/gregarndt/repos","events_url":"https://api.github.com/users/gregarndt/events{/privacy}","received_events_url":"https://api.github.com/users/gregarndt/received_events","type":"User","site_admin":false},"repo":{"id":23439744,"name":"docker-worker","full_name":"gregarndt/docker-worker","owner":{"login":"gregarndt","id":2592630,"avatar_url":"https://avatars.githubusercontent.com/u/2592630?v=3","gravatar_id":"","url":"https://api.github.com/users/gregarndt","html_url":"https://github.com/gregarndt","followers_url":"https://api.github.com/users/gregarndt/followers","following_url":"https://api.github.com/users/gregarndt/following{/other_user}","gists_url":"https://api.github.com/users/gregarndt/gists{/gist_id}","starred_url":"https://api.github.com/users/gregarndt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gregarndt/subscriptions","organizations_url":"https://api.github.com/users/gregarndt/orgs","repos_url":"https://api.github.com/users/gregarndt/repos","events_url":"https://api.github.com/users/gregarndt/events{/privacy}","received_events_url":"https://api.github.com/users/gregarndt/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gregarndt/docker-worker","description":"Docker worker for the cluster","fork":true,"url":"https://api.github.com/repos/gregarndt/docker-worker","forks_url":"https://api.github.com/repos/gregarndt/docker-worker/forks","keys_url":"https://api.github.com/repos/gregarndt/docker-worker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gregarndt/docker-worker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gregarndt/docker-worker/teams","hooks_url":"https://api.github.com/repos/gregarndt/docker-worker/hooks","issue_events_url":"https://api.github.com/repos/gregarndt/docker-worker/issues/events{/number}","events_url":"https://api.github.com/repos/gregarndt/docker-worker/events","assignees_url":"https://api.github.com/repos/gregarndt/docker-worker/assignees{/user}","branches_url":"https://api.github.com/repos/gregarndt/docker-worker/branches{/branch}","tags_url":"https://api.github.com/repos/gregarndt/docker-worker/tags","blobs_url":"https://api.github.com/repos/gregarndt/docker-worker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gregarndt/docker-worker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gregarndt/docker-worker/git/refs{/sha}","trees_url":"https://api.github.com/repos/gregarndt/docker-worker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gregarndt/docker-worker/statuses/{sha}","languages_url":"https://api.github.com/repos/gregarndt/docker-worker/languages","stargazers_url":"https://api.github.com/repos/gregarndt/docker-worker/stargazers","contributors_url":"https://api.github.com/repos/gregarndt/docker-worker/contributors","subscribers_url":"https://api.github.com/repos/gregarndt/docker-worker/subscribers","subscription_url":"https://api.github.com/repos/gregarndt/docker-worker/subscription","commits_url":"https://api.github.com/repos/gregarndt/docker-worker/commits{/sha}","git_commits_url":"https://api.github.com/repos/gregarndt/docker-worker/git/commits{/sha}","comments_url":"https://api.github.com/repos/gregarndt/docker-worker/comments{/number}","issue_comment_url":"https://api.github.com/repos/gregarndt/docker-worker/issues/comments{/number}","contents_url":"https://api.github.com/repos/gregarndt/docker-worker/contents/{+path}","compare_url":"https://api.github.com/repos/gregarndt/docker-worker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gregarndt/docker-worker/merges","archive_url":"https://api.github.com/repos/gregarndt/docker-worker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gregarndt/docker-worker/downloads","issues_url":"https://api.github.com/repos/gregarndt/docker-worker/issues{/number}","pulls_url":"https://api.github.com/repos/gregarndt/docker-worker/pulls{/number}","milestones_url":"https://api.github.com/repos/gregarndt/docker-worker/milestones{/number}","notifications_url":"https://api.github.com/repos/gregarndt/docker-worker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gregarndt/docker-worker/labels{/name}","releases_url":"https://api.github.com/repos/gregarndt/docker-worker/releases{/id}","created_at":"2014-08-28T19:09:49Z","updated_at":"2015-02-14T06:32:52Z","pushed_at":"2015-03-03T22:28:10Z","git_url":"git://github.com/gregarndt/docker-worker.git","ssh_url":"git@github.com:gregarndt/docker-worker.git","clone_url":"https://github.com/gregarndt/docker-worker.git","svn_url":"https://github.com/gregarndt/docker-worker","homepage":"","size":19646,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"taskcluster:master","ref":"master","sha":"da06c8714f68e1f1cb92f23216651f218186161e","user":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"repo":{"id":15545665,"name":"docker-worker","full_name":"taskcluster/docker-worker","owner":{"login":"taskcluster","id":6257436,"avatar_url":"https://avatars.githubusercontent.com/u/6257436?v=3","gravatar_id":"","url":"https://api.github.com/users/taskcluster","html_url":"https://github.com/taskcluster","followers_url":"https://api.github.com/users/taskcluster/followers","following_url":"https://api.github.com/users/taskcluster/following{/other_user}","gists_url":"https://api.github.com/users/taskcluster/gists{/gist_id}","starred_url":"https://api.github.com/users/taskcluster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/taskcluster/subscriptions","organizations_url":"https://api.github.com/users/taskcluster/orgs","repos_url":"https://api.github.com/users/taskcluster/repos","events_url":"https://api.github.com/users/taskcluster/events{/privacy}","received_events_url":"https://api.github.com/users/taskcluster/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/taskcluster/docker-worker","description":"Docker worker for the cluster","fork":false,"url":"https://api.github.com/repos/taskcluster/docker-worker","forks_url":"https://api.github.com/repos/taskcluster/docker-worker/forks","keys_url":"https://api.github.com/repos/taskcluster/docker-worker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/taskcluster/docker-worker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/taskcluster/docker-worker/teams","hooks_url":"https://api.github.com/repos/taskcluster/docker-worker/hooks","issue_events_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/events{/number}","events_url":"https://api.github.com/repos/taskcluster/docker-worker/events","assignees_url":"https://api.github.com/repos/taskcluster/docker-worker/assignees{/user}","branches_url":"https://api.github.com/repos/taskcluster/docker-worker/branches{/branch}","tags_url":"https://api.github.com/repos/taskcluster/docker-worker/tags","blobs_url":"https://api.github.com/repos/taskcluster/docker-worker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/taskcluster/docker-worker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/taskcluster/docker-worker/git/refs{/sha}","trees_url":"https://api.github.com/repos/taskcluster/docker-worker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/taskcluster/docker-worker/statuses/{sha}","languages_url":"https://api.github.com/repos/taskcluster/docker-worker/languages","stargazers_url":"https://api.github.com/repos/taskcluster/docker-worker/stargazers","contributors_url":"https://api.github.com/repos/taskcluster/docker-worker/contributors","subscribers_url":"https://api.github.com/repos/taskcluster/docker-worker/subscribers","subscription_url":"https://api.github.com/repos/taskcluster/docker-worker/subscription","commits_url":"https://api.github.com/repos/taskcluster/docker-worker/commits{/sha}","git_commits_url":"https://api.github.com/repos/taskcluster/docker-worker/git/commits{/sha}","comments_url":"https://api.github.com/repos/taskcluster/docker-worker/comments{/number}","issue_comment_url":"https://api.github.com/repos/taskcluster/docker-worker/issues/comments{/number}","contents_url":"https://api.github.com/repos/taskcluster/docker-worker/contents/{+path}","compare_url":"https://api.github.com/repos/taskcluster/docker-worker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/taskcluster/docker-worker/merges","archive_url":"https://api.github.com/repos/taskcluster/docker-worker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/taskcluster/docker-worker/downloads","issues_url":"https://api.github.com/repos/taskcluster/docker-worker/issues{/number}","pulls_url":"https://api.github.com/repos/taskcluster/docker-worker/pulls{/number}","milestones_url":"https://api.github.com/repos/taskcluster/docker-worker/milestones{/number}","notifications_url":"https://api.github.com/repos/taskcluster/docker-worker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/taskcluster/docker-worker/labels{/name}","releases_url":"https://api.github.com/repos/taskcluster/docker-worker/releases{/id}","created_at":"2013-12-31T07:38:22Z","updated_at":"2015-02-14T03:17:42Z","pushed_at":"2015-02-14T03:17:42Z","git_url":"git://github.com/taskcluster/docker-worker.git","ssh_url":"git@github.com:taskcluster/docker-worker.git","clone_url":"https://github.com/taskcluster/docker-worker.git","svn_url":"https://github.com/taskcluster/docker-worker","homepage":"","size":21650,"stargazers_count":9,"watchers_count":9,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":3,"forks":7,"open_issues":3,"watchers":9,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66"},"html":{"href":"https://github.com/taskcluster/docker-worker/pull/66"},"issue":{"href":"https://api.github.com/repos/taskcluster/docker-worker/issues/66"},"comments":{"href":"https://api.github.com/repos/taskcluster/docker-worker/issues/66/comments"},"review_comments":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66/comments"},"review_comment":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/taskcluster/docker-worker/pulls/66/commits"},"statuses":{"href":"https://api.github.com/repos/taskcluster/docker-worker/statuses/2e66ba69ef175fc16949bf19c01ac10b37bdfa71"}}}}