{"action":"created","comment":{"url":"https://api.github.com/repos/linkedin/cruise-control/pulls/comments/217207907","pull_request_review_id":154856441,"id":217207907,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNzIwNzkwNw==","diff_hunk":"@@ -0,0 +1,456 @@\n+/*\n+ * Copyright 2018 LinkedIn Corp. Licensed under the BSD 2-Clause License (the \"License\"). See License in the project root for license information.\n+ */\n+\n+package com.linkedin.kafka.cruisecontrol.servlet;\n+\n+import com.codahale.metrics.Gauge;\n+import com.codahale.metrics.MetricRegistry;\n+import com.linkedin.kafka.cruisecontrol.async.OperationFuture;\n+import com.linkedin.kafka.cruisecontrol.common.KafkaCruiseControlThreadFactory;\n+import java.io.Closeable;\n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.HashMap;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.Map;\n+import java.util.Objects;\n+import java.util.UUID;\n+import java.util.concurrent.Executors;\n+import java.util.concurrent.ScheduledExecutorService;\n+import java.util.concurrent.TimeUnit;\n+import java.util.function.Supplier;\n+import javax.servlet.http.HttpServletRequest;\n+import javax.servlet.http.HttpServletResponse;\n+import javax.servlet.http.HttpSession;\n+import org.apache.kafka.common.utils.Time;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+\n+/**\n+ * {@link UserTaskManager} keeps track of long-running request.\n+ *\n+ * {@link HttpServletRequest} can execute for long durations. The servlet submits the asynchronous tasks and returns the\n+ * progress of the operation instead of blocking for the operation to complete. {@link UserTaskManager} maintains the\n+ * mapping of Request URL and {@link HttpSession} to UserTaskID({@link UUID}). To fetch the status of a request, the\n+ * client can use the same Request ULR along with session cookie to retrieve the current status. The status of the\n+ * request can also be fetched using the UserTaskID. '/user_tasks' endpoint can be used to fetch all the active and\n+ * recently completed UserTasks.\n+ */\n+public class UserTaskManager implements Closeable {\n+  public static final String USER_TASK_HEADER_NAME = \"User-Task-ID\";\n+  public static final long USER_TASK_SCANNER_PERIOD_SECONDS = 5;\n+\n+  private static final Logger LOG = LoggerFactory.getLogger(UserTaskManager.class);\n+  private final Map<SessionKey, UUID> _sessionToUserTaskIdMap;\n+  private final Map<UUID, UserTaskInfo> _activeUserTaskIdToFuturesMap;\n+  private final Map<UUID, UserTaskInfo> _completedUserTaskIdToFuturesMap;","path":"cruise-control/src/main/java/com/linkedin/kafka/cruisecontrol/servlet/UserTaskManager.java","position":49,"original_position":49,"commit_id":"90f0de8186018c2b9e9bb801357b844121a73c48","original_commit_id":"90f0de8186018c2b9e9bb801357b844121a73c48","user":{"login":"efeg","id":1877110,"node_id":"MDQ6VXNlcjE4NzcxMTA=","avatar_url":"https://avatars2.githubusercontent.com/u/1877110?v=4","gravatar_id":"","url":"https://api.github.com/users/efeg","html_url":"https://github.com/efeg","followers_url":"https://api.github.com/users/efeg/followers","following_url":"https://api.github.com/users/efeg/following{/other_user}","gists_url":"https://api.github.com/users/efeg/gists{/gist_id}","starred_url":"https://api.github.com/users/efeg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/efeg/subscriptions","organizations_url":"https://api.github.com/users/efeg/orgs","repos_url":"https://api.github.com/users/efeg/repos","events_url":"https://api.github.com/users/efeg/events{/privacy}","received_events_url":"https://api.github.com/users/efeg/received_events","type":"User","site_admin":false},"body":"Nit: Would using a `SortedMap` for `_activeUserTaskIdToFuturesMap` and `_completedUserTaskIdToFuturesMap` help us improve usability by sorting the tasks based on a comparator ordering `UUID`?","created_at":"2018-09-12T22:20:27Z","updated_at":"2018-09-12T22:59:47Z","html_url":"https://github.com/linkedin/cruise-control/pull/304#discussion_r217207907","pull_request_url":"https://api.github.com/repos/linkedin/cruise-control/pulls/304","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/linkedin/cruise-control/pulls/comments/217207907"},"html":{"href":"https://github.com/linkedin/cruise-control/pull/304#discussion_r217207907"},"pull_request":{"href":"https://api.github.com/repos/linkedin/cruise-control/pulls/304"}}},"pull_request":{"url":"https://api.github.com/repos/linkedin/cruise-control/pulls/304","id":210331654,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEwMzMxNjU0","html_url":"https://github.com/linkedin/cruise-control/pull/304","diff_url":"https://github.com/linkedin/cruise-control/pull/304.diff","patch_url":"https://github.com/linkedin/cruise-control/pull/304.patch","issue_url":"https://api.github.com/repos/linkedin/cruise-control/issues/304","number":304,"state":"open","locked":false,"title":"Support a user-task based management to replace session based managment.","user":{"login":"abhishekmendhekar","id":3779349,"node_id":"MDQ6VXNlcjM3NzkzNDk=","avatar_url":"https://avatars3.githubusercontent.com/u/3779349?v=4","gravatar_id":"","url":"https://api.github.com/users/abhishekmendhekar","html_url":"https://github.com/abhishekmendhekar","followers_url":"https://api.github.com/users/abhishekmendhekar/followers","following_url":"https://api.github.com/users/abhishekmendhekar/following{/other_user}","gists_url":"https://api.github.com/users/abhishekmendhekar/gists{/gist_id}","starred_url":"https://api.github.com/users/abhishekmendhekar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abhishekmendhekar/subscriptions","organizations_url":"https://api.github.com/users/abhishekmendhekar/orgs","repos_url":"https://api.github.com/users/abhishekmendhekar/repos","events_url":"https://api.github.com/users/abhishekmendhekar/events{/privacy}","received_events_url":"https://api.github.com/users/abhishekmendhekar/received_events","type":"User","site_admin":false},"body":"CruiseControl used sessions to manage async operations from users and\r\nlimited it by the number of active sessions.\r\n\r\nThis commit introduces the concept of UserTaskManager (replaces SessionManager).\r\nIt's responsible for managing active tasks using User-Task-ID defined in\r\nthe HTTP request/response header.\r\n\r\nHttpSessions can still be used to fetch the status of an asynchronous operation\r\nbut it can be overridden by adding the User-Task-Id as the request header.\r\nEvery asynchronous request will return the User-Task-Id in the response headers that\r\ncan be used by the client to fetch the asynchronous operation status.\r\n\r\nA new Http request is added to report the status active tasks that are in\r\nprogress.","created_at":"2018-08-23T05:06:14Z","updated_at":"2018-09-12T22:59:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9b5185dfb78f693602f6e046939b03ed0b2c36a1","assignee":{"login":"abhishekmendhekar","id":3779349,"node_id":"MDQ6VXNlcjM3NzkzNDk=","avatar_url":"https://avatars3.githubusercontent.com/u/3779349?v=4","gravatar_id":"","url":"https://api.github.com/users/abhishekmendhekar","html_url":"https://github.com/abhishekmendhekar","followers_url":"https://api.github.com/users/abhishekmendhekar/followers","following_url":"https://api.github.com/users/abhishekmendhekar/following{/other_user}","gists_url":"https://api.github.com/users/abhishekmendhekar/gists{/gist_id}","starred_url":"https://api.github.com/users/abhishekmendhekar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abhishekmendhekar/subscriptions","organizations_url":"https://api.github.com/users/abhishekmendhekar/orgs","repos_url":"https://api.github.com/users/abhishekmendhekar/repos","events_url":"https://api.github.com/users/abhishekmendhekar/events{/privacy}","received_events_url":"https://api.github.com/users/abhishekmendhekar/received_events","type":"User","site_admin":false},"assignees":[{"login":"abhishekmendhekar","id":3779349,"node_id":"MDQ6VXNlcjM3NzkzNDk=","avatar_url":"https://avatars3.githubusercontent.com/u/3779349?v=4","gravatar_id":"","url":"https://api.github.com/users/abhishekmendhekar","html_url":"https://github.com/abhishekmendhekar","followers_url":"https://api.github.com/users/abhishekmendhekar/followers","following_url":"https://api.github.com/users/abhishekmendhekar/following{/other_user}","gists_url":"https://api.github.com/users/abhishekmendhekar/gists{/gist_id}","starred_url":"https://api.github.com/users/abhishekmendhekar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abhishekmendhekar/subscriptions","organizations_url":"https://api.github.com/users/abhishekmendhekar/orgs","repos_url":"https://api.github.com/users/abhishekmendhekar/repos","events_url":"https://api.github.com/users/abhishekmendhekar/events{/privacy}","received_events_url":"https://api.github.com/users/abhishekmendhekar/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":669368641,"node_id":"MDU6TGFiZWw2NjkzNjg2NDE=","url":"https://api.github.com/repos/linkedin/cruise-control/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"milestone":null,"commits_url":"https://api.github.com/repos/linkedin/cruise-control/pulls/304/commits","review_comments_url":"https://api.github.com/repos/linkedin/cruise-control/pulls/304/comments","review_comment_url":"https://api.github.com/repos/linkedin/cruise-control/pulls/comments{/number}","comments_url":"https://api.github.com/repos/linkedin/cruise-control/issues/304/comments","statuses_url":"https://api.github.com/repos/linkedin/cruise-control/statuses/90f0de8186018c2b9e9bb801357b844121a73c48","head":{"label":"abhishekmendhekar:session-management","ref":"session-management","sha":"90f0de8186018c2b9e9bb801357b844121a73c48","user":{"login":"abhishekmendhekar","id":3779349,"node_id":"MDQ6VXNlcjM3NzkzNDk=","avatar_url":"https://avatars3.githubusercontent.com/u/3779349?v=4","gravatar_id":"","url":"https://api.github.com/users/abhishekmendhekar","html_url":"https://github.com/abhishekmendhekar","followers_url":"https://api.github.com/users/abhishekmendhekar/followers","following_url":"https://api.github.com/users/abhishekmendhekar/following{/other_user}","gists_url":"https://api.github.com/users/abhishekmendhekar/gists{/gist_id}","starred_url":"https://api.github.com/users/abhishekmendhekar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abhishekmendhekar/subscriptions","organizations_url":"https://api.github.com/users/abhishekmendhekar/orgs","repos_url":"https://api.github.com/users/abhishekmendhekar/repos","events_url":"https://api.github.com/users/abhishekmendhekar/events{/privacy}","received_events_url":"https://api.github.com/users/abhishekmendhekar/received_events","type":"User","site_admin":false},"repo":{"id":101915532,"node_id":"MDEwOlJlcG9zaXRvcnkxMDE5MTU1MzI=","name":"cruise-control","full_name":"abhishekmendhekar/cruise-control","owner":{"login":"abhishekmendhekar","id":3779349,"node_id":"MDQ6VXNlcjM3NzkzNDk=","avatar_url":"https://avatars3.githubusercontent.com/u/3779349?v=4","gravatar_id":"","url":"https://api.github.com/users/abhishekmendhekar","html_url":"https://github.com/abhishekmendhekar","followers_url":"https://api.github.com/users/abhishekmendhekar/followers","following_url":"https://api.github.com/users/abhishekmendhekar/following{/other_user}","gists_url":"https://api.github.com/users/abhishekmendhekar/gists{/gist_id}","starred_url":"https://api.github.com/users/abhishekmendhekar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abhishekmendhekar/subscriptions","organizations_url":"https://api.github.com/users/abhishekmendhekar/orgs","repos_url":"https://api.github.com/users/abhishekmendhekar/repos","events_url":"https://api.github.com/users/abhishekmendhekar/events{/privacy}","received_events_url":"https://api.github.com/users/abhishekmendhekar/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/abhishekmendhekar/cruise-control","description":"Cruise-control is the first of its kind to fully automate the dynamic workload rebalance and self-healing of a kafka cluster. It provides great value to Kafka users by simplifying the operation of Kafka clusters.","fork":true,"url":"https://api.github.com/repos/abhishekmendhekar/cruise-control","forks_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/forks","keys_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/keys{/key_id}","collaborators_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/teams","hooks_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/hooks","issue_events_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/issues/events{/number}","events_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/events","assignees_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/assignees{/user}","branches_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/branches{/branch}","tags_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/tags","blobs_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/git/refs{/sha}","trees_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/git/trees{/sha}","statuses_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/statuses/{sha}","languages_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/languages","stargazers_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/stargazers","contributors_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/contributors","subscribers_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/subscribers","subscription_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/subscription","commits_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/commits{/sha}","git_commits_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/git/commits{/sha}","comments_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/comments{/number}","issue_comment_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/issues/comments{/number}","contents_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/contents/{+path}","compare_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/compare/{base}...{head}","merges_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/merges","archive_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/downloads","issues_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/issues{/number}","pulls_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/pulls{/number}","milestones_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/milestones{/number}","notifications_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/labels{/name}","releases_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/releases{/id}","deployments_url":"https://api.github.com/repos/abhishekmendhekar/cruise-control/deployments","created_at":"2017-08-30T18:27:23Z","updated_at":"2018-08-23T04:56:51Z","pushed_at":"2018-09-12T04:35:27Z","git_url":"git://github.com/abhishekmendhekar/cruise-control.git","ssh_url":"git@github.com:abhishekmendhekar/cruise-control.git","clone_url":"https://github.com/abhishekmendhekar/cruise-control.git","svn_url":"https://github.com/abhishekmendhekar/cruise-control","homepage":"","size":1800,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"bsd-2-clause","name":"BSD 2-Clause \"Simplified\" License","spdx_id":"BSD-2-Clause","url":"https://api.github.com/licenses/bsd-2-clause","node_id":"MDc6TGljZW5zZTQ="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"linkedin:master","ref":"master","sha":"4742a649ff5aa8f370b8f0ff0463dcbd938d7aef","user":{"login":"linkedin","id":357098,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM1NzA5OA==","avatar_url":"https://avatars3.githubusercontent.com/u/357098?v=4","gravatar_id":"","url":"https://api.github.com/users/linkedin","html_url":"https://github.com/linkedin","followers_url":"https://api.github.com/users/linkedin/followers","following_url":"https://api.github.com/users/linkedin/following{/other_user}","gists_url":"https://api.github.com/users/linkedin/gists{/gist_id}","starred_url":"https://api.github.com/users/linkedin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/linkedin/subscriptions","organizations_url":"https://api.github.com/users/linkedin/orgs","repos_url":"https://api.github.com/users/linkedin/repos","events_url":"https://api.github.com/users/linkedin/events{/privacy}","received_events_url":"https://api.github.com/users/linkedin/received_events","type":"Organization","site_admin":false},"repo":{"id":100402355,"node_id":"MDEwOlJlcG9zaXRvcnkxMDA0MDIzNTU=","name":"cruise-control","full_name":"linkedin/cruise-control","owner":{"login":"linkedin","id":357098,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM1NzA5OA==","avatar_url":"https://avatars3.githubusercontent.com/u/357098?v=4","gravatar_id":"","url":"https://api.github.com/users/linkedin","html_url":"https://github.com/linkedin","followers_url":"https://api.github.com/users/linkedin/followers","following_url":"https://api.github.com/users/linkedin/following{/other_user}","gists_url":"https://api.github.com/users/linkedin/gists{/gist_id}","starred_url":"https://api.github.com/users/linkedin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/linkedin/subscriptions","organizations_url":"https://api.github.com/users/linkedin/orgs","repos_url":"https://api.github.com/users/linkedin/repos","events_url":"https://api.github.com/users/linkedin/events{/privacy}","received_events_url":"https://api.github.com/users/linkedin/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/linkedin/cruise-control","description":"Cruise-control is the first of its kind to fully automate the dynamic workload rebalance and self-healing of a kafka cluster. It provides great value to Kafka users by simplifying the operation of Kafka clusters.","fork":false,"url":"https://api.github.com/repos/linkedin/cruise-control","forks_url":"https://api.github.com/repos/linkedin/cruise-control/forks","keys_url":"https://api.github.com/repos/linkedin/cruise-control/keys{/key_id}","collaborators_url":"https://api.github.com/repos/linkedin/cruise-control/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/linkedin/cruise-control/teams","hooks_url":"https://api.github.com/repos/linkedin/cruise-control/hooks","issue_events_url":"https://api.github.com/repos/linkedin/cruise-control/issues/events{/number}","events_url":"https://api.github.com/repos/linkedin/cruise-control/events","assignees_url":"https://api.github.com/repos/linkedin/cruise-control/assignees{/user}","branches_url":"https://api.github.com/repos/linkedin/cruise-control/branches{/branch}","tags_url":"https://api.github.com/repos/linkedin/cruise-control/tags","blobs_url":"https://api.github.com/repos/linkedin/cruise-control/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/linkedin/cruise-control/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/linkedin/cruise-control/git/refs{/sha}","trees_url":"https://api.github.com/repos/linkedin/cruise-control/git/trees{/sha}","statuses_url":"https://api.github.com/repos/linkedin/cruise-control/statuses/{sha}","languages_url":"https://api.github.com/repos/linkedin/cruise-control/languages","stargazers_url":"https://api.github.com/repos/linkedin/cruise-control/stargazers","contributors_url":"https://api.github.com/repos/linkedin/cruise-control/contributors","subscribers_url":"https://api.github.com/repos/linkedin/cruise-control/subscribers","subscription_url":"https://api.github.com/repos/linkedin/cruise-control/subscription","commits_url":"https://api.github.com/repos/linkedin/cruise-control/commits{/sha}","git_commits_url":"https://api.github.com/repos/linkedin/cruise-control/git/commits{/sha}","comments_url":"https://api.github.com/repos/linkedin/cruise-control/comments{/number}","issue_comment_url":"https://api.github.com/repos/linkedin/cruise-control/issues/comments{/number}","contents_url":"https://api.github.com/repos/linkedin/cruise-control/contents/{+path}","compare_url":"https://api.github.com/repos/linkedin/cruise-control/compare/{base}...{head}","merges_url":"https://api.github.com/repos/linkedin/cruise-control/merges","archive_url":"https://api.github.com/repos/linkedin/cruise-control/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/linkedin/cruise-control/downloads","issues_url":"https://api.github.com/repos/linkedin/cruise-control/issues{/number}","pulls_url":"https://api.github.com/repos/linkedin/cruise-control/pulls{/number}","milestones_url":"https://api.github.com/repos/linkedin/cruise-control/milestones{/number}","notifications_url":"https://api.github.com/repos/linkedin/cruise-control/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/linkedin/cruise-control/labels{/name}","releases_url":"https://api.github.com/repos/linkedin/cruise-control/releases{/id}","deployments_url":"https://api.github.com/repos/linkedin/cruise-control/deployments","created_at":"2017-08-15T17:32:10Z","updated_at":"2018-09-11T19:52:26Z","pushed_at":"2018-09-12T20:34:40Z","git_url":"git://github.com/linkedin/cruise-control.git","ssh_url":"git@github.com:linkedin/cruise-control.git","clone_url":"https://github.com/linkedin/cruise-control.git","svn_url":"https://github.com/linkedin/cruise-control","homepage":"","size":1842,"stargazers_count":821,"watchers_count":821,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":165,"mirror_url":null,"archived":false,"open_issues_count":52,"license":{"key":"bsd-2-clause","name":"BSD 2-Clause \"Simplified\" License","spdx_id":"BSD-2-Clause","url":"https://api.github.com/licenses/bsd-2-clause","node_id":"MDc6TGljZW5zZTQ="},"forks":165,"open_issues":52,"watchers":821,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/linkedin/cruise-control/pulls/304"},"html":{"href":"https://github.com/linkedin/cruise-control/pull/304"},"issue":{"href":"https://api.github.com/repos/linkedin/cruise-control/issues/304"},"comments":{"href":"https://api.github.com/repos/linkedin/cruise-control/issues/304/comments"},"review_comments":{"href":"https://api.github.com/repos/linkedin/cruise-control/pulls/304/comments"},"review_comment":{"href":"https://api.github.com/repos/linkedin/cruise-control/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/linkedin/cruise-control/pulls/304/commits"},"statuses":{"href":"https://api.github.com/repos/linkedin/cruise-control/statuses/90f0de8186018c2b9e9bb801357b844121a73c48"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"efeg"}}