{"action":"created","comment":{"url":"https://api.github.com/repos/crate/crate/pulls/comments/75438454","id":75438454,"diff_hunk":"@@ -22,196 +22,144 @@\n package io.crate.executor.transport.task.elasticsearch;\n \n import com.google.common.base.Function;\n-import com.google.common.base.Optional;\n import com.google.common.collect.ImmutableList;\n import com.google.common.collect.ImmutableSet;\n-import com.google.common.util.concurrent.SettableFuture;\n import io.crate.Constants;\n import io.crate.analyze.symbol.InputColumn;\n import io.crate.analyze.symbol.Symbol;\n import io.crate.analyze.symbol.ValueSymbolVisitor;\n import io.crate.analyze.where.DocKeys;\n-import io.crate.core.collections.Bucket;\n-import io.crate.core.collections.Buckets;\n-import io.crate.executor.QueryResult;\n-import io.crate.executor.TaskResult;\n+import io.crate.executor.JobTask;\n+import io.crate.executor.transport.TransportActionProvider;\n+import io.crate.jobs.AbstractExecutionSubContext;\n import io.crate.jobs.JobContextService;\n+import io.crate.jobs.JobExecutionContext;\n import io.crate.metadata.ColumnIdent;\n import io.crate.metadata.Functions;\n import io.crate.metadata.PartitionName;\n import io.crate.metadata.Reference;\n import io.crate.metadata.doc.DocSysColumns;\n import io.crate.metadata.doc.DocTableInfo;\n-import io.crate.operation.QueryResultRowDownstream;\n import io.crate.operation.projectors.*;\n import io.crate.planner.node.dql.ESGet;\n import io.crate.planner.projection.Projection;\n import io.crate.planner.projection.TopNProjection;\n import org.apache.lucene.util.BytesRef;\n import org.elasticsearch.action.ActionListener;\n import org.elasticsearch.action.ActionRequest;\n+import org.elasticsearch.action.ActionResponse;\n import org.elasticsearch.action.get.*;\n import org.elasticsearch.action.support.TransportAction;\n+import org.elasticsearch.common.logging.ESLogger;\n+import org.elasticsearch.common.logging.Loggers;\n import org.elasticsearch.common.xcontent.support.XContentMapValues;\n import org.elasticsearch.index.IndexNotFoundException;\n import org.elasticsearch.search.fetch.source.FetchSourceContext;\n \n+import javax.annotation.Nullable;\n import java.util.*;\n \n-public class ESGetTask extends EsJobContextTask {\n+public class ESGetTask extends JobTask {\n \n     private final static SymbolToFieldExtractor<GetResponse> SYMBOL_TO_FIELD_EXTRACTOR =\n             new SymbolToFieldExtractor<>(new GetResponseFieldExtractorFactory());\n \n     private final static Set<ColumnIdent> FETCH_SOURCE_COLUMNS = ImmutableSet.of(DocSysColumns.DOC, DocSysColumns.RAW);\n+    private final ProjectorFactory projectorFactory;\n+    private final TransportActionProvider transportActionProvider;\n+    private final ESGet esGet;\n \n-    public ESGetTask(Functions functions,\n-                     ProjectorFactory projectorFactory,\n-                     TransportMultiGetAction multiGetAction,\n-                     TransportGetAction getAction,\n-                     ESGet esGet,\n-                     JobContextService jobContextService) {\n-        super(esGet.jobId(), esGet.executionPhaseId(), 1, jobContextService);\n+    private final JobContextService jobContextService;\n+    private final List<Function<GetResponse, Object>> extractors;\n+    private final FetchSourceContext fsc;\n \n-        assert multiGetAction != null;\n-        assert getAction != null;\n-        assert esGet.docKeys().size() > 0;\n-        assert esGet.limit() != 0 : \"shouldn't execute ESGetTask if limit is 0\";\n+    static abstract class JobContext<Action extends TransportAction<Request, Response>,\n+        Request extends ActionRequest, Response extends ActionResponse> extends AbstractExecutionSubContext\n+        implements ActionListener<Response>{\n \n-        ActionListener listener;\n-        ActionRequest request;\n-        TransportAction transportAction;\n-        FlatProjectorChain projectorChain = null;\n+        private static final ESLogger LOGGER = Loggers.getLogger(JobContext.class);\n \n-        SettableFuture<TaskResult> result = SettableFuture.create();\n-        results.add(result);\n \n-        GetResponseContext ctx = new GetResponseContext(functions, esGet);\n-        List<Function<GetResponse, Object>> extractors = getFieldExtractors(esGet, ctx);\n-        FetchSourceContext fsc = getFetchSourceContext(ctx.references());\n-        if (esGet.docKeys().size() > 1) {\n-            request = prepareMultiGetRequest(esGet, fsc);\n-            transportAction = multiGetAction;\n-            QueryResultRowDownstream queryResultRowDownstream = new QueryResultRowDownstream(result);\n-            projectorChain = getFlatProjectorChain(projectorFactory, esGet, queryResultRowDownstream);\n-            RowReceiver rowReceiver = projectorChain.firstProjector();\n-            listener = new MultiGetResponseListener(extractors, rowReceiver);\n-        } else {\n-            request = prepareGetRequest(esGet, fsc);\n-            transportAction = getAction;\n-            listener = new GetResponseListener(result, extractors, esGet.tableInfo().isPartitioned());\n-        }\n+        private final Request request;\n+        protected RowReceiver downstream;\n \n-        createContextBuilder(\"lookup by primary key\", ImmutableList.of(request), ImmutableList.of(listener),\n-                transportAction, projectorChain);\n-    }\n+        private final Action transportAction;\n+        protected final ESGetTask task;\n \n-    private static FetchSourceContext getFetchSourceContext(List<Reference> references) {\n-        List<String> includes = new ArrayList<>(references.size());\n-        for (Reference ref : references) {\n-            if (ref.ident().columnIdent().isSystemColumn() &&\n-                FETCH_SOURCE_COLUMNS.contains(ref.ident().columnIdent())) {\n-                return new FetchSourceContext(true);\n-            }\n-            includes.add(ref.ident().columnIdent().name());\n-        }\n-        if (includes.size() > 0) {\n-            return new FetchSourceContext(includes.toArray(new String[includes.size()]));\n+        JobContext(ESGetTask task, Action transportAction, RowReceiver downstream) {\n+            super(task.esGet.executionPhaseId(), LOGGER);\n+            this.task = task;\n+            this.transportAction = transportAction;\n+            this.request = prepareRequest(task.esGet, task.fsc);\n+            this.downstream = downstream;\n         }\n-        return new FetchSourceContext(false);\n-    }\n \n-    private static List<Function<GetResponse, Object>> getFieldExtractors(ESGet node, GetResponseContext ctx) {\n-        List<Function<GetResponse, Object>> extractors = new ArrayList<>(node.outputs().size() + node.sortSymbols().size());\n-        for (Symbol symbol : node.outputs()) {\n-            extractors.add(SYMBOL_TO_FIELD_EXTRACTOR.convert(symbol, ctx));\n-        }\n-        for (Symbol symbol : node.sortSymbols()) {\n-            extractors.add(SYMBOL_TO_FIELD_EXTRACTOR.convert(symbol, ctx));\n-        }\n-        return extractors;\n-    }\n+        protected abstract Request prepareRequest(ESGet node, FetchSourceContext fsc);\n \n-    public static String indexName(DocTableInfo tableInfo, Optional<List<BytesRef>> values) {\n-        if (tableInfo.isPartitioned()) {\n-            return new PartitionName(tableInfo.ident(), values.get()).asIndexName();\n-        } else {\n-            return tableInfo.ident().indexName();\n+        @Override\n+        protected void innerStart() {\n+            transportAction.execute(request, this);\n         }\n     }\n \n-    private GetRequest prepareGetRequest(ESGet node, FetchSourceContext fsc) {\n-        DocKeys.DocKey docKey = node.docKeys().getOnlyKey();\n-        GetRequest getRequest = new GetRequest(indexName(node.tableInfo(), docKey.partitionValues()),\n-                Constants.DEFAULT_MAPPING_TYPE, docKey.id());\n-        getRequest.fetchSourceContext(fsc);\n-        getRequest.realtime(true);\n-        getRequest.routing(docKey.routing());\n-        return getRequest;\n-    }\n+    private static class MultiGetJobContext extends JobContext<TransportMultiGetAction, MultiGetRequest, MultiGetResponse> {\n+\n \n-    private MultiGetRequest prepareMultiGetRequest(ESGet node, FetchSourceContext fsc) {\n-        MultiGetRequest multiGetRequest = new MultiGetRequest();\n-        for (DocKeys.DocKey key : node.docKeys()) {\n-            MultiGetRequest.Item item = new MultiGetRequest.Item(\n-                    indexName(node.tableInfo(), key.partitionValues()), Constants.DEFAULT_MAPPING_TYPE, key.id());\n-            item.fetchSourceContext(fsc);\n-            item.routing(key.routing());\n-            multiGetRequest.add(item);\n+        MultiGetJobContext(ESGetTask task,\n+                                  TransportMultiGetAction transportAction,\n+                                  RowReceiver downstream) {\n+            super(task, transportAction, downstream);\n+            assert task.esGet.docKeys().size() > 1;\n+            assert task.projectorFactory != null;\n         }\n-        multiGetRequest.realtime(true);\n-        return multiGetRequest;\n-    }\n \n-    private FlatProjectorChain getFlatProjectorChain(ProjectorFactory projectorFactory,\n-                                                     ESGet node,\n-                                                     QueryResultRowDownstream queryResultRowDownstream) {\n-        if (node.limit() > TopN.NO_LIMIT || node.offset() > 0 || !node.sortSymbols().isEmpty()) {\n-            List<Symbol> orderBySymbols = new ArrayList<>(node.sortSymbols().size());\n-            for (Symbol symbol : node.sortSymbols()) {\n-                int i = node.outputs().indexOf(symbol);\n-                if (i < 0) {\n-                    orderBySymbols.add(new InputColumn(node.outputs().size() + orderBySymbols.size()));\n-                } else {\n-                    orderBySymbols.add(new InputColumn(i));\n+        @Override\n+        protected void innerPrepare() throws Exception {\n+            FlatProjectorChain projectorChain = getFlatProjectorChain(downstream);\n+            downstream = projectorChain.firstProjector();\n+            projectorChain.prepare();\n+        }\n+\n+        private FlatProjectorChain getFlatProjectorChain(RowReceiver downstream) {\n+            if (task.esGet.limit() > TopN.NO_LIMIT || task.esGet.offset() > 0 || !task.esGet.sortSymbols().isEmpty()) {","path":"sql/src/main/java/io/crate/executor/transport/task/elasticsearch/ESGetTask.java","position":205,"original_position":205,"commit_id":"def87a1d3df884de978a0fde5b2f66523aaa0279","original_commit_id":"def87a1d3df884de978a0fde5b2f66523aaa0279","user":{"login":"dobe","id":48020,"avatar_url":"https://avatars.githubusercontent.com/u/48020?v=3","gravatar_id":"","url":"https://api.github.com/users/dobe","html_url":"https://github.com/dobe","followers_url":"https://api.github.com/users/dobe/followers","following_url":"https://api.github.com/users/dobe/following{/other_user}","gists_url":"https://api.github.com/users/dobe/gists{/gist_id}","starred_url":"https://api.github.com/users/dobe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dobe/subscriptions","organizations_url":"https://api.github.com/users/dobe/orgs","repos_url":"https://api.github.com/users/dobe/repos","events_url":"https://api.github.com/users/dobe/events{/privacy}","received_events_url":"https://api.github.com/users/dobe/received_events","type":"User","site_admin":false},"body":"just moved this method ... however i think if we remove it we need to add an assertion since logically this is not true. i would keep it","created_at":"2016-08-19T07:28:08Z","updated_at":"2016-08-19T07:28:08Z","html_url":"https://github.com/crate/crate/pull/3989#discussion_r75438454","pull_request_url":"https://api.github.com/repos/crate/crate/pulls/3989","_links":{"self":{"href":"https://api.github.com/repos/crate/crate/pulls/comments/75438454"},"html":{"href":"https://github.com/crate/crate/pull/3989#discussion_r75438454"},"pull_request":{"href":"https://api.github.com/repos/crate/crate/pulls/3989"}}},"pull_request":{"url":"https://api.github.com/repos/crate/crate/pulls/3989","id":81928129,"html_url":"https://github.com/crate/crate/pull/3989","diff_url":"https://github.com/crate/crate/pull/3989.diff","patch_url":"https://github.com/crate/crate/pull/3989.patch","issue_url":"https://api.github.com/repos/crate/crate/issues/3989","number":3989,"state":"open","locked":false,"title":"remove TaskResult","user":{"login":"dobe","id":48020,"avatar_url":"https://avatars.githubusercontent.com/u/48020?v=3","gravatar_id":"","url":"https://api.github.com/users/dobe","html_url":"https://github.com/dobe","followers_url":"https://api.github.com/users/dobe/followers","following_url":"https://api.github.com/users/dobe/following{/other_user}","gists_url":"https://api.github.com/users/dobe/gists{/gist_id}","starred_url":"https://api.github.com/users/dobe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dobe/subscriptions","organizations_url":"https://api.github.com/users/dobe/orgs","repos_url":"https://api.github.com/users/dobe/repos","events_url":"https://api.github.com/users/dobe/events{/privacy}","received_events_url":"https://api.github.com/users/dobe/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-08-19T05:25:07Z","updated_at":"2016-08-19T07:28:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7e29d4d11c37c427fa452e81664ed24bb69efbc1","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/crate/crate/pulls/3989/commits","review_comments_url":"https://api.github.com/repos/crate/crate/pulls/3989/comments","review_comment_url":"https://api.github.com/repos/crate/crate/pulls/comments{/number}","comments_url":"https://api.github.com/repos/crate/crate/issues/3989/comments","statuses_url":"https://api.github.com/repos/crate/crate/statuses/def87a1d3df884de978a0fde5b2f66523aaa0279","head":{"label":"crate:dobe/removetaskresult","ref":"dobe/removetaskresult","sha":"def87a1d3df884de978a0fde5b2f66523aaa0279","user":{"login":"crate","id":4048232,"avatar_url":"https://avatars.githubusercontent.com/u/4048232?v=3","gravatar_id":"","url":"https://api.github.com/users/crate","html_url":"https://github.com/crate","followers_url":"https://api.github.com/users/crate/followers","following_url":"https://api.github.com/users/crate/following{/other_user}","gists_url":"https://api.github.com/users/crate/gists{/gist_id}","starred_url":"https://api.github.com/users/crate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crate/subscriptions","organizations_url":"https://api.github.com/users/crate/orgs","repos_url":"https://api.github.com/users/crate/repos","events_url":"https://api.github.com/users/crate/events{/privacy}","received_events_url":"https://api.github.com/users/crate/received_events","type":"Organization","site_admin":false},"repo":{"id":9342529,"name":"crate","full_name":"crate/crate","owner":{"login":"crate","id":4048232,"avatar_url":"https://avatars.githubusercontent.com/u/4048232?v=3","gravatar_id":"","url":"https://api.github.com/users/crate","html_url":"https://github.com/crate","followers_url":"https://api.github.com/users/crate/followers","following_url":"https://api.github.com/users/crate/following{/other_user}","gists_url":"https://api.github.com/users/crate/gists{/gist_id}","starred_url":"https://api.github.com/users/crate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crate/subscriptions","organizations_url":"https://api.github.com/users/crate/orgs","repos_url":"https://api.github.com/users/crate/repos","events_url":"https://api.github.com/users/crate/events{/privacy}","received_events_url":"https://api.github.com/users/crate/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/crate/crate","description":"Crate.IO: The fast, scalable, easy to use SQL database with native full text search","fork":false,"url":"https://api.github.com/repos/crate/crate","forks_url":"https://api.github.com/repos/crate/crate/forks","keys_url":"https://api.github.com/repos/crate/crate/keys{/key_id}","collaborators_url":"https://api.github.com/repos/crate/crate/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/crate/crate/teams","hooks_url":"https://api.github.com/repos/crate/crate/hooks","issue_events_url":"https://api.github.com/repos/crate/crate/issues/events{/number}","events_url":"https://api.github.com/repos/crate/crate/events","assignees_url":"https://api.github.com/repos/crate/crate/assignees{/user}","branches_url":"https://api.github.com/repos/crate/crate/branches{/branch}","tags_url":"https://api.github.com/repos/crate/crate/tags","blobs_url":"https://api.github.com/repos/crate/crate/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/crate/crate/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/crate/crate/git/refs{/sha}","trees_url":"https://api.github.com/repos/crate/crate/git/trees{/sha}","statuses_url":"https://api.github.com/repos/crate/crate/statuses/{sha}","languages_url":"https://api.github.com/repos/crate/crate/languages","stargazers_url":"https://api.github.com/repos/crate/crate/stargazers","contributors_url":"https://api.github.com/repos/crate/crate/contributors","subscribers_url":"https://api.github.com/repos/crate/crate/subscribers","subscription_url":"https://api.github.com/repos/crate/crate/subscription","commits_url":"https://api.github.com/repos/crate/crate/commits{/sha}","git_commits_url":"https://api.github.com/repos/crate/crate/git/commits{/sha}","comments_url":"https://api.github.com/repos/crate/crate/comments{/number}","issue_comment_url":"https://api.github.com/repos/crate/crate/issues/comments{/number}","contents_url":"https://api.github.com/repos/crate/crate/contents/{+path}","compare_url":"https://api.github.com/repos/crate/crate/compare/{base}...{head}","merges_url":"https://api.github.com/repos/crate/crate/merges","archive_url":"https://api.github.com/repos/crate/crate/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/crate/crate/downloads","issues_url":"https://api.github.com/repos/crate/crate/issues{/number}","pulls_url":"https://api.github.com/repos/crate/crate/pulls{/number}","milestones_url":"https://api.github.com/repos/crate/crate/milestones{/number}","notifications_url":"https://api.github.com/repos/crate/crate/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/crate/crate/labels{/name}","releases_url":"https://api.github.com/repos/crate/crate/releases{/id}","deployments_url":"https://api.github.com/repos/crate/crate/deployments","created_at":"2013-04-10T09:17:16Z","updated_at":"2016-08-18T02:34:06Z","pushed_at":"2016-08-19T07:27:03Z","git_url":"git://github.com/crate/crate.git","ssh_url":"git@github.com:crate/crate.git","clone_url":"https://github.com/crate/crate.git","svn_url":"https://github.com/crate/crate","homepage":"https://crate.io","size":73701,"stargazers_count":1350,"watchers_count":1350,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":149,"mirror_url":null,"open_issues_count":43,"forks":149,"open_issues":43,"watchers":1350,"default_branch":"master"}},"base":{"label":"crate:master","ref":"master","sha":"a189474e5aac754963958e8e0e5b5dfcde2675b4","user":{"login":"crate","id":4048232,"avatar_url":"https://avatars.githubusercontent.com/u/4048232?v=3","gravatar_id":"","url":"https://api.github.com/users/crate","html_url":"https://github.com/crate","followers_url":"https://api.github.com/users/crate/followers","following_url":"https://api.github.com/users/crate/following{/other_user}","gists_url":"https://api.github.com/users/crate/gists{/gist_id}","starred_url":"https://api.github.com/users/crate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crate/subscriptions","organizations_url":"https://api.github.com/users/crate/orgs","repos_url":"https://api.github.com/users/crate/repos","events_url":"https://api.github.com/users/crate/events{/privacy}","received_events_url":"https://api.github.com/users/crate/received_events","type":"Organization","site_admin":false},"repo":{"id":9342529,"name":"crate","full_name":"crate/crate","owner":{"login":"crate","id":4048232,"avatar_url":"https://avatars.githubusercontent.com/u/4048232?v=3","gravatar_id":"","url":"https://api.github.com/users/crate","html_url":"https://github.com/crate","followers_url":"https://api.github.com/users/crate/followers","following_url":"https://api.github.com/users/crate/following{/other_user}","gists_url":"https://api.github.com/users/crate/gists{/gist_id}","starred_url":"https://api.github.com/users/crate/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/crate/subscriptions","organizations_url":"https://api.github.com/users/crate/orgs","repos_url":"https://api.github.com/users/crate/repos","events_url":"https://api.github.com/users/crate/events{/privacy}","received_events_url":"https://api.github.com/users/crate/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/crate/crate","description":"Crate.IO: The fast, scalable, easy to use SQL database with native full text search","fork":false,"url":"https://api.github.com/repos/crate/crate","forks_url":"https://api.github.com/repos/crate/crate/forks","keys_url":"https://api.github.com/repos/crate/crate/keys{/key_id}","collaborators_url":"https://api.github.com/repos/crate/crate/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/crate/crate/teams","hooks_url":"https://api.github.com/repos/crate/crate/hooks","issue_events_url":"https://api.github.com/repos/crate/crate/issues/events{/number}","events_url":"https://api.github.com/repos/crate/crate/events","assignees_url":"https://api.github.com/repos/crate/crate/assignees{/user}","branches_url":"https://api.github.com/repos/crate/crate/branches{/branch}","tags_url":"https://api.github.com/repos/crate/crate/tags","blobs_url":"https://api.github.com/repos/crate/crate/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/crate/crate/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/crate/crate/git/refs{/sha}","trees_url":"https://api.github.com/repos/crate/crate/git/trees{/sha}","statuses_url":"https://api.github.com/repos/crate/crate/statuses/{sha}","languages_url":"https://api.github.com/repos/crate/crate/languages","stargazers_url":"https://api.github.com/repos/crate/crate/stargazers","contributors_url":"https://api.github.com/repos/crate/crate/contributors","subscribers_url":"https://api.github.com/repos/crate/crate/subscribers","subscription_url":"https://api.github.com/repos/crate/crate/subscription","commits_url":"https://api.github.com/repos/crate/crate/commits{/sha}","git_commits_url":"https://api.github.com/repos/crate/crate/git/commits{/sha}","comments_url":"https://api.github.com/repos/crate/crate/comments{/number}","issue_comment_url":"https://api.github.com/repos/crate/crate/issues/comments{/number}","contents_url":"https://api.github.com/repos/crate/crate/contents/{+path}","compare_url":"https://api.github.com/repos/crate/crate/compare/{base}...{head}","merges_url":"https://api.github.com/repos/crate/crate/merges","archive_url":"https://api.github.com/repos/crate/crate/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/crate/crate/downloads","issues_url":"https://api.github.com/repos/crate/crate/issues{/number}","pulls_url":"https://api.github.com/repos/crate/crate/pulls{/number}","milestones_url":"https://api.github.com/repos/crate/crate/milestones{/number}","notifications_url":"https://api.github.com/repos/crate/crate/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/crate/crate/labels{/name}","releases_url":"https://api.github.com/repos/crate/crate/releases{/id}","deployments_url":"https://api.github.com/repos/crate/crate/deployments","created_at":"2013-04-10T09:17:16Z","updated_at":"2016-08-18T02:34:06Z","pushed_at":"2016-08-19T07:27:03Z","git_url":"git://github.com/crate/crate.git","ssh_url":"git@github.com:crate/crate.git","clone_url":"https://github.com/crate/crate.git","svn_url":"https://github.com/crate/crate","homepage":"https://crate.io","size":73701,"stargazers_count":1350,"watchers_count":1350,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":149,"mirror_url":null,"open_issues_count":43,"forks":149,"open_issues":43,"watchers":1350,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/crate/crate/pulls/3989"},"html":{"href":"https://github.com/crate/crate/pull/3989"},"issue":{"href":"https://api.github.com/repos/crate/crate/issues/3989"},"comments":{"href":"https://api.github.com/repos/crate/crate/issues/3989/comments"},"review_comments":{"href":"https://api.github.com/repos/crate/crate/pulls/3989/comments"},"review_comment":{"href":"https://api.github.com/repos/crate/crate/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/crate/crate/pulls/3989/commits"},"statuses":{"href":"https://api.github.com/repos/crate/crate/statuses/def87a1d3df884de978a0fde5b2f66523aaa0279"}}}}
{"actor":{"display_login":"dobe"}}