{"action":"created","comment":{"url":"https://api.github.com/repos/apache/incubator-druid/pulls/comments/202759974","pull_request_review_id":137520553,"id":202759974,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwMjc1OTk3NA==","diff_hunk":"@@ -169,34 +186,64 @@ public CachingClusteredClient(\n     return new SpecificQueryRunnable<>(queryPlus, responseContext).run(timelineConverter);\n   }\n \n+  private <T> Sequence<T> runAndMergeWithTimelineChange(\n+      final Query<T> query,\n+      final QueryPlus<T> queryPlus,\n+      final Map<String, Object> responseContext,\n+      final UnaryOperator<TimelineLookup<String, ServerSelector>> timelineConverter\n+  )\n+  {\n+    final Stream<? extends Sequence<T>> sequences = run(\n+        queryPlus,\n+        responseContext,\n+        timelineConverter\n+    );\n+    final OptionalLong mergeBatch = QueryContexts.getIntermediateMergeBatchThreshold(query);\n+    if (mergeBatch.isPresent()) {\n+      return MergeWorkTask.parallelMerge(\n+          query.getResultOrdering(),\n+          sequences.parallel(),\n+          mergeBatch.getAsLong(),\n+          mergeFjp\n+      );\n+    } else {\n+      return new MergeSequence<>(\n+          query.getResultOrdering(),\n+          Sequences.simple(sequences)\n+      );\n+    }\n+  }\n+\n   @Override\n   public <T> QueryRunner<T> getQueryRunnerForSegments(final Query<T> query, final Iterable<SegmentDescriptor> specs)","path":"server/src/main/java/io/druid/client/CachingClusteredClient.java","position":179,"original_position":179,"commit_id":"19290ecd3e50b476aa5b6aa148047062ec106cea","original_commit_id":"a1d286309ab645adf590dfd383d58060029bd428","user":{"login":"drcrallen","id":8213081,"node_id":"MDQ6VXNlcjgyMTMwODE=","avatar_url":"https://avatars2.githubusercontent.com/u/8213081?v=4","gravatar_id":"","url":"https://api.github.com/users/drcrallen","html_url":"https://github.com/drcrallen","followers_url":"https://api.github.com/users/drcrallen/followers","following_url":"https://api.github.com/users/drcrallen/following{/other_user}","gists_url":"https://api.github.com/users/drcrallen/gists{/gist_id}","starred_url":"https://api.github.com/users/drcrallen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drcrallen/subscriptions","organizations_url":"https://api.github.com/users/drcrallen/orgs","repos_url":"https://api.github.com/users/drcrallen/repos","events_url":"https://api.github.com/users/drcrallen/events{/privacy}","received_events_url":"https://api.github.com/users/drcrallen/received_events","type":"User","site_admin":false},"body":"fixed","created_at":"2018-07-16T17:13:35Z","updated_at":"2018-07-16T17:13:35Z","html_url":"https://github.com/apache/incubator-druid/pull/5913#discussion_r202759974","pull_request_url":"https://api.github.com/repos/apache/incubator-druid/pulls/5913","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/apache/incubator-druid/pulls/comments/202759974"},"html":{"href":"https://github.com/apache/incubator-druid/pull/5913#discussion_r202759974"},"pull_request":{"href":"https://api.github.com/repos/apache/incubator-druid/pulls/5913"}},"in_reply_to_id":202551031},"pull_request":{"url":"https://api.github.com/repos/apache/incubator-druid/pulls/5913","id":197882510,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk3ODgyNTEw","html_url":"https://github.com/apache/incubator-druid/pull/5913","diff_url":"https://github.com/apache/incubator-druid/pull/5913.diff","patch_url":"https://github.com/apache/incubator-druid/pull/5913.patch","issue_url":"https://api.github.com/repos/apache/incubator-druid/issues/5913","number":5913,"state":"open","locked":false,"title":"Move Caching Cluster Client to java streams and allow parallel intermediate merges","user":{"login":"drcrallen","id":8213081,"node_id":"MDQ6VXNlcjgyMTMwODE=","avatar_url":"https://avatars2.githubusercontent.com/u/8213081?v=4","gravatar_id":"","url":"https://api.github.com/users/drcrallen","html_url":"https://github.com/drcrallen","followers_url":"https://api.github.com/users/drcrallen/followers","following_url":"https://api.github.com/users/drcrallen/following{/other_user}","gists_url":"https://api.github.com/users/drcrallen/gists{/gist_id}","starred_url":"https://api.github.com/users/drcrallen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drcrallen/subscriptions","organizations_url":"https://api.github.com/users/drcrallen/orgs","repos_url":"https://api.github.com/users/drcrallen/repos","events_url":"https://api.github.com/users/drcrallen/events{/privacy}","received_events_url":"https://api.github.com/users/drcrallen/received_events","type":"User","site_admin":false},"body":"We are seeing severe broker bottlenecks for certain types of queries. The existing Sequence paradigm does a folding reduction whereby the results from all the historicals and real-time nodes are folded into a single accumulator. This accumulation can be a major bottleneck in terms of performance for these large queries. TopN queries with results on order 10k returning from hundreds of nodes can take many seconds (in excess of 40s in some cases) to do the merge on the broker! A cpu-time flame graph of such a scenario can be seen below:\r\n\r\n<img width=\"1730\" alt=\"screen shot 2018-06-22 at 1 39 00 pm\" src=\"https://user-images.githubusercontent.com/8213081/42004711-e1b553ae-7a25-11e8-8fbe-d9035a438017.png\">\r\n\r\nIn an attempt to \"fix\" this bottleneck, I was having a hard time following the logic in `CachingClusteredClient`. So I re-wrote a bunch of the logic in java8 streams, attempting to retain as much of the original functionality as possible. I also added many more comments as to why different sections were doing what they are doing. As a killer addition, a new query context `intermediateMergeBatchThreshold` is added which allows parallel intermediate merges\r\n\r\n### Intermediate merges\r\n\r\nThe Sequences produced by the druid client connections are collected in a Stream. If the query context `intermediateMergeBatchThreshold` is specified, then Spliterators are forked off of the Sequence Stream in batches according to the threshold if possible. Failure to do so reverts to prior merge behavior. These Sequences are fully materialized by working in a ForkJoinPool, and the results are Accumulated (reduce-fold-left kind of operation) on a first-available basis. All of the results fetched from cache are also another Sequence that gets merged in. \r\n\r\n### Why Fork Join Pool?\r\n\r\nThe \"work\" for the intermediate merges is done in a dedicated `ForkJoinPool`. A fork-join-pool was used instead of an Executor service in order to accommodate dynamic expansion of the worker pool. Basically to use a worker setup slightly better than running all the folding accumulation in the http server thread. The forking and joining semantics are used, but any effects of potentially blocking operations (like QTL) are not attempted to be accounted for. As such, having a specific pool of resources was chosen with the hope that eventually it can be more intelligent about being kind when doing potentially blocking operations. This is no worse than a fixed pool executor service and, when done properly, can handle new threads to circumvent blocked threads in a better manner. Future enhancements can include merge work task prioritization based on query priority, as well as enhancements to account for potentially blocking code.\r\n\r\nAdditionally, with how the `fork` and `join` items are intended to work, a `ListenableFuture` style workflow can be attained by doing a `join` of a task, and performing a task based on the result, so long as the `join` is executed in the FJP.\r\n\r\n### Other changes\r\n\r\nStreaming methods are added to the Cache interface in order to accommodate changes in the caching cluster client.\r\n\r\nAdditionally, small changes in the way the per-druid-node Sequences are initiated are present. The proposed implementation causes the direct druid client to fire off queries to all the nodes regardless of intermediate merges being used or not. The cached and uncached results now feed through the same \"Stream\" and are simply resolved as either a Merge Sequence (for cached results) or a Sequence from the direct druid client (for cache misses). This caused some unit tests to be changed to allow timeline lookups when previously there were none.\r\n\r\n### Results\r\n\r\nInitial internal results show that query speeds were improved by 85% for large queries with `intermediateMergeBatchThreshold` set. Impact on smaller queries have not been fully investigated, and impact when `intermediateMergeBatchThreshold` is not set (just the new Stream workflow) is not fully exercised.\r\n\r\nWork can clearly be seen being done in the ForkJoinPool as per:\r\n\r\n<img width=\"1496\" alt=\"screen shot 2018-06-27 at 10 26 51 am\" src=\"https://user-images.githubusercontent.com/8213081/42005277-5d6ec6b8-7a28-11e8-8a87-63c089b3a67b.png\">\r\n\r\nWith the final merge in the `QueryResource.doPost` stack still present as per\r\n\r\n<img width=\"673\" alt=\"screen shot 2018-06-27 at 10 27 22 am\" src=\"https://user-images.githubusercontent.com/8213081/42005309-83e13d80-7a28-11e8-9a84-0076379b5161.png\">\r\n\r\n### Not included here\r\n\r\nThere are other items of interest for larger clusters, such as broker-brokers (or cross-broker merges). Hopefully the migrating of CachingClusterClient onto java streams makes such a possibility easier in the future.\r\n\r\nThe impact on heap pressure from turning on this feature has not been fully explored. Since this feature is intended to help large clusters with large results, this could be a major problem if not taken care.\r\n\r\nHandling back-pressure better would be a nice improvement. For example, if druid-client request returns could be controlled in a better manner to prevent an arbitrary number of them from returning an arbitrary size of result, then that would help larger results to be handled by the brokers.\r\n\r\n### TODO\r\n\r\n- [x] I'm still missing some unit tests for the cache changes in the hybrid cache\r\n\r\n### Conclusion\r\n\r\nThis is a huge performance boon (85%) for one of our core use cases. It would be interesting to see if this helps with large group-by queries as well. Since this is an opt-in feature that is very close to prior behavior when disabled, hopefully the risk for the change is very small, while the clarity of how the data stream is handled is clearer (or at least documented more).","created_at":"2018-06-27T23:47:17Z","updated_at":"2018-07-16T17:13:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"896f12b674b4326d869743bf4191e8861f8b298e","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":219585748,"node_id":"MDU6TGFiZWwyMTk1ODU3NDg=","url":"https://api.github.com/repos/apache/incubator-druid/labels/Area%20-%20Querying","name":"Area - Querying","color":"fef2c0","default":false},{"id":321808195,"node_id":"MDU6TGFiZWwzMjE4MDgxOTU=","url":"https://api.github.com/repos/apache/incubator-druid/labels/Improvement","name":"Improvement","color":"0052cc","default":false},{"id":120288359,"node_id":"MDU6TGFiZWwxMjAyODgzNTk=","url":"https://api.github.com/repos/apache/incubator-druid/labels/Performance","name":"Performance","color":"fbca04","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/apache/incubator-druid/pulls/5913/commits","review_comments_url":"https://api.github.com/repos/apache/incubator-druid/pulls/5913/comments","review_comment_url":"https://api.github.com/repos/apache/incubator-druid/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/incubator-druid/issues/5913/comments","statuses_url":"https://api.github.com/repos/apache/incubator-druid/statuses/19290ecd3e50b476aa5b6aa148047062ec106cea","head":{"label":"drcrallen:cachingclient/streamport","ref":"cachingclient/streamport","sha":"19290ecd3e50b476aa5b6aa148047062ec106cea","user":{"login":"drcrallen","id":8213081,"node_id":"MDQ6VXNlcjgyMTMwODE=","avatar_url":"https://avatars2.githubusercontent.com/u/8213081?v=4","gravatar_id":"","url":"https://api.github.com/users/drcrallen","html_url":"https://github.com/drcrallen","followers_url":"https://api.github.com/users/drcrallen/followers","following_url":"https://api.github.com/users/drcrallen/following{/other_user}","gists_url":"https://api.github.com/users/drcrallen/gists{/gist_id}","starred_url":"https://api.github.com/users/drcrallen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drcrallen/subscriptions","organizations_url":"https://api.github.com/users/drcrallen/orgs","repos_url":"https://api.github.com/users/drcrallen/repos","events_url":"https://api.github.com/users/drcrallen/events{/privacy}","received_events_url":"https://api.github.com/users/drcrallen/received_events","type":"User","site_admin":false},"repo":{"id":28249158,"node_id":"MDEwOlJlcG9zaXRvcnkyODI0OTE1OA==","name":"druid","full_name":"drcrallen/druid","owner":{"login":"drcrallen","id":8213081,"node_id":"MDQ6VXNlcjgyMTMwODE=","avatar_url":"https://avatars2.githubusercontent.com/u/8213081?v=4","gravatar_id":"","url":"https://api.github.com/users/drcrallen","html_url":"https://github.com/drcrallen","followers_url":"https://api.github.com/users/drcrallen/followers","following_url":"https://api.github.com/users/drcrallen/following{/other_user}","gists_url":"https://api.github.com/users/drcrallen/gists{/gist_id}","starred_url":"https://api.github.com/users/drcrallen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/drcrallen/subscriptions","organizations_url":"https://api.github.com/users/drcrallen/orgs","repos_url":"https://api.github.com/users/drcrallen/repos","events_url":"https://api.github.com/users/drcrallen/events{/privacy}","received_events_url":"https://api.github.com/users/drcrallen/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/drcrallen/druid","description":"Real²time Exploratory Analytics on Large Datasets","fork":true,"url":"https://api.github.com/repos/drcrallen/druid","forks_url":"https://api.github.com/repos/drcrallen/druid/forks","keys_url":"https://api.github.com/repos/drcrallen/druid/keys{/key_id}","collaborators_url":"https://api.github.com/repos/drcrallen/druid/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/drcrallen/druid/teams","hooks_url":"https://api.github.com/repos/drcrallen/druid/hooks","issue_events_url":"https://api.github.com/repos/drcrallen/druid/issues/events{/number}","events_url":"https://api.github.com/repos/drcrallen/druid/events","assignees_url":"https://api.github.com/repos/drcrallen/druid/assignees{/user}","branches_url":"https://api.github.com/repos/drcrallen/druid/branches{/branch}","tags_url":"https://api.github.com/repos/drcrallen/druid/tags","blobs_url":"https://api.github.com/repos/drcrallen/druid/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/drcrallen/druid/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/drcrallen/druid/git/refs{/sha}","trees_url":"https://api.github.com/repos/drcrallen/druid/git/trees{/sha}","statuses_url":"https://api.github.com/repos/drcrallen/druid/statuses/{sha}","languages_url":"https://api.github.com/repos/drcrallen/druid/languages","stargazers_url":"https://api.github.com/repos/drcrallen/druid/stargazers","contributors_url":"https://api.github.com/repos/drcrallen/druid/contributors","subscribers_url":"https://api.github.com/repos/drcrallen/druid/subscribers","subscription_url":"https://api.github.com/repos/drcrallen/druid/subscription","commits_url":"https://api.github.com/repos/drcrallen/druid/commits{/sha}","git_commits_url":"https://api.github.com/repos/drcrallen/druid/git/commits{/sha}","comments_url":"https://api.github.com/repos/drcrallen/druid/comments{/number}","issue_comment_url":"https://api.github.com/repos/drcrallen/druid/issues/comments{/number}","contents_url":"https://api.github.com/repos/drcrallen/druid/contents/{+path}","compare_url":"https://api.github.com/repos/drcrallen/druid/compare/{base}...{head}","merges_url":"https://api.github.com/repos/drcrallen/druid/merges","archive_url":"https://api.github.com/repos/drcrallen/druid/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/drcrallen/druid/downloads","issues_url":"https://api.github.com/repos/drcrallen/druid/issues{/number}","pulls_url":"https://api.github.com/repos/drcrallen/druid/pulls{/number}","milestones_url":"https://api.github.com/repos/drcrallen/druid/milestones{/number}","notifications_url":"https://api.github.com/repos/drcrallen/druid/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/drcrallen/druid/labels{/name}","releases_url":"https://api.github.com/repos/drcrallen/druid/releases{/id}","deployments_url":"https://api.github.com/repos/drcrallen/druid/deployments","created_at":"2014-12-19T22:40:47Z","updated_at":"2018-07-06T15:32:31Z","pushed_at":"2018-07-16T17:11:02Z","git_url":"git://github.com/drcrallen/druid.git","ssh_url":"git@github.com:drcrallen/druid.git","clone_url":"https://github.com/drcrallen/druid.git","svn_url":"https://github.com/drcrallen/druid","homepage":"http://druid.io","size":136175,"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":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"31c2179fe1daa564e918f4ba64937743a45132a1","user":{"login":"apache","id":47359,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ3MzU5","avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":6358188,"node_id":"MDEwOlJlcG9zaXRvcnk2MzU4MTg4","name":"incubator-druid","full_name":"apache/incubator-druid","owner":{"login":"apache","id":47359,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ3MzU5","avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/incubator-druid","description":"Apache Druid (Incubating) - Column oriented distributed data store ideal for powering interactive applications","fork":false,"url":"https://api.github.com/repos/apache/incubator-druid","forks_url":"https://api.github.com/repos/apache/incubator-druid/forks","keys_url":"https://api.github.com/repos/apache/incubator-druid/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/incubator-druid/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/incubator-druid/teams","hooks_url":"https://api.github.com/repos/apache/incubator-druid/hooks","issue_events_url":"https://api.github.com/repos/apache/incubator-druid/issues/events{/number}","events_url":"https://api.github.com/repos/apache/incubator-druid/events","assignees_url":"https://api.github.com/repos/apache/incubator-druid/assignees{/user}","branches_url":"https://api.github.com/repos/apache/incubator-druid/branches{/branch}","tags_url":"https://api.github.com/repos/apache/incubator-druid/tags","blobs_url":"https://api.github.com/repos/apache/incubator-druid/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/incubator-druid/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/incubator-druid/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/incubator-druid/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/incubator-druid/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/incubator-druid/languages","stargazers_url":"https://api.github.com/repos/apache/incubator-druid/stargazers","contributors_url":"https://api.github.com/repos/apache/incubator-druid/contributors","subscribers_url":"https://api.github.com/repos/apache/incubator-druid/subscribers","subscription_url":"https://api.github.com/repos/apache/incubator-druid/subscription","commits_url":"https://api.github.com/repos/apache/incubator-druid/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/incubator-druid/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/incubator-druid/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/incubator-druid/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/incubator-druid/contents/{+path}","compare_url":"https://api.github.com/repos/apache/incubator-druid/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/incubator-druid/merges","archive_url":"https://api.github.com/repos/apache/incubator-druid/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/incubator-druid/downloads","issues_url":"https://api.github.com/repos/apache/incubator-druid/issues{/number}","pulls_url":"https://api.github.com/repos/apache/incubator-druid/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/incubator-druid/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/incubator-druid/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/incubator-druid/labels{/name}","releases_url":"https://api.github.com/repos/apache/incubator-druid/releases{/id}","deployments_url":"https://api.github.com/repos/apache/incubator-druid/deployments","created_at":"2012-10-23T19:08:07Z","updated_at":"2018-07-16T16:40:23Z","pushed_at":"2018-07-16T17:11:04Z","git_url":"git://github.com/apache/incubator-druid.git","ssh_url":"git@github.com:apache/incubator-druid.git","clone_url":"https://github.com/apache/incubator-druid.git","svn_url":"https://github.com/apache/incubator-druid","homepage":"http://druid.io","size":140815,"stargazers_count":6756,"watchers_count":6756,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1658,"mirror_url":null,"archived":false,"open_issues_count":1088,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":1658,"open_issues":1088,"watchers":6756,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/incubator-druid/pulls/5913"},"html":{"href":"https://github.com/apache/incubator-druid/pull/5913"},"issue":{"href":"https://api.github.com/repos/apache/incubator-druid/issues/5913"},"comments":{"href":"https://api.github.com/repos/apache/incubator-druid/issues/5913/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/incubator-druid/pulls/5913/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/incubator-druid/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/incubator-druid/pulls/5913/commits"},"statuses":{"href":"https://api.github.com/repos/apache/incubator-druid/statuses/19290ecd3e50b476aa5b6aa148047062ec106cea"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"drcrallen"}}