{"action":"created","comment":{"url":"https://api.github.com/repos/nuxeo/nuxeo/pulls/comments/193699779","pull_request_review_id":126690478,"id":193699779,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5MzY5OTc3OQ==","diff_hunk":"@@ -0,0 +1,173 @@\n+/*\n+ * (C) Copyright 2018 Nuxeo (http://nuxeo.com/) and others.\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the \"License\");\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *     http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an \"AS IS\" BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ *\n+ * Contributors:\n+ *       Kevin Leturc <kleturc@nuxeo.com>\n+ */\n+package org.nuxeo.ecm.core.bulk;\n+\n+import static java.nio.charset.StandardCharsets.UTF_8;\n+import static org.nuxeo.ecm.core.bulk.BulkServiceImpl.SCROLLED_DOCUMENT_COUNT;\n+import static org.nuxeo.ecm.core.bulk.BulkServiceImpl.SET_STREAM_NAME;\n+import static org.nuxeo.ecm.core.bulk.BulkServiceImpl.STATE;\n+import static org.nuxeo.ecm.core.bulk.BulkStatus.State.BUILDING;\n+import static org.nuxeo.ecm.core.bulk.BulkStatus.State.COMPLETED;\n+import static org.nuxeo.ecm.core.bulk.BulkStatus.State.SCHEDULED;\n+\n+import java.io.IOException;\n+import java.io.UnsupportedEncodingException;\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.Map;\n+\n+import org.apache.commons.logging.Log;\n+import org.apache.commons.logging.LogFactory;\n+import org.nuxeo.ecm.core.api.CloseableCoreSession;\n+import org.nuxeo.ecm.core.api.CoreInstance;\n+import org.nuxeo.ecm.core.api.NuxeoException;\n+import org.nuxeo.ecm.core.api.ScrollResult;\n+import org.nuxeo.lib.stream.computation.AbstractComputation;\n+import org.nuxeo.lib.stream.computation.ComputationContext;\n+import org.nuxeo.lib.stream.computation.Record;\n+import org.nuxeo.lib.stream.computation.Topology;\n+import org.nuxeo.runtime.api.Framework;\n+import org.nuxeo.runtime.kv.KeyValueService;\n+import org.nuxeo.runtime.kv.KeyValueStore;\n+import org.nuxeo.runtime.stream.StreamProcessorTopology;\n+import org.nuxeo.runtime.transaction.TransactionHelper;\n+\n+import com.fasterxml.jackson.databind.ObjectMapper;\n+\n+/**\n+ * Computation that consumes a stream of {@link BulkCommand} and send to another stream the document ids on which this\n+ * command run.\n+ *\n+ * @since 10.2\n+ */\n+public class StreamBulkScroller implements StreamProcessorTopology {\n+\n+    private static final Log log = LogFactory.getLog(StreamBulkScroller.class);\n+\n+    public static final String COMPUTATION_NAME = \"bulkDocumentScroller\";\n+\n+    public static final String SCROLL_BATCH_SIZE_OPT = \"scrollBatchSize\";\n+\n+    public static final String SCROLL_KEEP_ALIVE_SECONDS_OPT = \"scrollKeepAlive\";\n+\n+    public static final int DEFAULT_SCROLL_BATCH_SIZE = 100;\n+\n+    public static final int DEFAULT_SCROLL_KEEPALIVE_SECONDS = 60;\n+\n+    @Override\n+    public Topology getTopology(Map<String, String> options) {\n+        // retrieve options\n+        int scrollBatchSize = getOptionAsInteger(options, SCROLL_BATCH_SIZE_OPT, DEFAULT_SCROLL_BATCH_SIZE);\n+        int scrollKeepAliveSeconds = getOptionAsInteger(options, SCROLL_KEEP_ALIVE_SECONDS_OPT,\n+                DEFAULT_SCROLL_KEEPALIVE_SECONDS);\n+        // retrieve bulk operations to deduce output streams\n+        BulkAdminService service = Framework.getService(BulkAdminService.class);\n+        String kvStore = service.getKeyValueStore();\n+        List<String> operations = service.getOperations();\n+        List<String> mapping = new ArrayList<>();\n+        mapping.add(\"i1:\" + SET_STREAM_NAME);\n+        int i = 1;\n+        for (String operation : operations) {\n+            mapping.add(String.format(\"o%s:%s\", i, operation));\n+            i++;\n+        }\n+        return Topology.builder()\n+                       .addComputation( //\n+                               () -> new BulkDocumentScrollerComputation(COMPUTATION_NAME, operations.size(), kvStore,\n+                                       scrollBatchSize, scrollKeepAliveSeconds), //\n+                               mapping)\n+                       .build();\n+    }\n+\n+    public static class BulkDocumentScrollerComputation extends AbstractComputation {\n+\n+        protected final KeyValueStore kvStore;\n+\n+        protected final int scrollBatchSize;\n+\n+        protected final int scrollKeepAliveSeconds;\n+\n+        public BulkDocumentScrollerComputation(String name, int nbOutputStreams, String kvStore, int scrollBatchSize,\n+                int scrollKeepAliveSeconds) {\n+            super(name, 1, nbOutputStreams);\n+            this.kvStore = Framework.getService(KeyValueService.class).getKeyValueStore(kvStore);\n+            this.scrollBatchSize = scrollBatchSize;\n+            this.scrollKeepAliveSeconds = scrollKeepAliveSeconds;\n+        }\n+\n+        @Override\n+        public void processRecord(ComputationContext context, String inputStreamName, Record record) {\n+            TransactionHelper.runInTransaction(() -> processRecord(context, record));\n+        }\n+\n+        protected void processRecord(ComputationContext context, Record record) {\n+            try {\n+                BulkCommand command = getBulkCommandJson(record.data);\n+                if (!kvStore.compareAndSet(record.key + STATE, SCHEDULED.toString(), BUILDING.toString())) {\n+                    log.error(\"Discard record: \" + record + \" because it's already building\");\n+                    return;\n+                }\n+                try (CloseableCoreSession session = CoreInstance.openCoreSession(command.getRepository(),\n+                        command.getUsername())) {\n+                    // scroll documents\n+                    ScrollResult<String> scroll = session.scroll(command.getQuery(), scrollBatchSize,\n+                            scrollKeepAliveSeconds);\n+                    long documentCount = 0;\n+                    while (scroll.hasResults()) {\n+                        List<String> docIds = scroll.getResults();\n+                        // send these ids as keys to the appropriate stream\n+                        // key will be bulkOperationId/docId\n+                        // value/data is a BulkCommand serialized as JSON\n+                        docIds.forEach(docId -> context.produceRecord(command.getOperation(), record.key + '/' + docId,\n+                                record.data));","path":"nuxeo-core/nuxeo-core-bulk/src/main/java/org/nuxeo/ecm/core/bulk/StreamBulkScroller.java","position":138,"original_position":138,"commit_id":"9a40ae328ccdfe2a12b138df2d184a0348f5e4b3","original_commit_id":"9a40ae328ccdfe2a12b138df2d184a0348f5e4b3","user":{"login":"bdelbosc","id":589079,"node_id":"MDQ6VXNlcjU4OTA3OQ==","avatar_url":"https://avatars1.githubusercontent.com/u/589079?v=4","gravatar_id":"","url":"https://api.github.com/users/bdelbosc","html_url":"https://github.com/bdelbosc","followers_url":"https://api.github.com/users/bdelbosc/followers","following_url":"https://api.github.com/users/bdelbosc/following{/other_user}","gists_url":"https://api.github.com/users/bdelbosc/gists{/gist_id}","starred_url":"https://api.github.com/users/bdelbosc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bdelbosc/subscriptions","organizations_url":"https://api.github.com/users/bdelbosc/orgs","repos_url":"https://api.github.com/users/bdelbosc/repos","events_url":"https://api.github.com/users/bdelbosc/events{/privacy}","received_events_url":"https://api.github.com/users/bdelbosc/received_events","type":"User","site_admin":false},"body":"ok for the first impl but adding the command in each record is too much overhead when having millions of ids. An option for next version is to output record with multiple ids. At this point I don't know if we need a key instead of simply roundrobin on partition and if we need the command. ","created_at":"2018-06-07T10:32:49Z","updated_at":"2018-06-07T10:50:59Z","html_url":"https://github.com/nuxeo/nuxeo/pull/2054#discussion_r193699779","pull_request_url":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/nuxeo/nuxeo/pulls/comments/193699779"},"html":{"href":"https://github.com/nuxeo/nuxeo/pull/2054#discussion_r193699779"},"pull_request":{"href":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054"}}},"pull_request":{"url":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054","id":193244934,"node_id":"MDExOlB1bGxSZXF1ZXN0MTkzMjQ0OTM0","html_url":"https://github.com/nuxeo/nuxeo/pull/2054","diff_url":"https://github.com/nuxeo/nuxeo/pull/2054.diff","patch_url":"https://github.com/nuxeo/nuxeo/pull/2054.patch","issue_url":"https://api.github.com/repos/nuxeo/nuxeo/issues/2054","number":2054,"state":"open","locked":false,"title":"Bulk Operation Framework part 1","user":{"login":"funshodavid","id":20774651,"node_id":"MDQ6VXNlcjIwNzc0NjUx","avatar_url":"https://avatars0.githubusercontent.com/u/20774651?v=4","gravatar_id":"","url":"https://api.github.com/users/funshodavid","html_url":"https://github.com/funshodavid","followers_url":"https://api.github.com/users/funshodavid/followers","following_url":"https://api.github.com/users/funshodavid/following{/other_user}","gists_url":"https://api.github.com/users/funshodavid/gists{/gist_id}","starred_url":"https://api.github.com/users/funshodavid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/funshodavid/subscriptions","organizations_url":"https://api.github.com/users/funshodavid/orgs","repos_url":"https://api.github.com/users/funshodavid/repos","events_url":"https://api.github.com/users/funshodavid/events{/privacy}","received_events_url":"https://api.github.com/users/funshodavid/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-06-07T08:44:18Z","updated_at":"2018-06-07T10:50:59Z","closed_at":null,"merged_at":null,"merge_commit_sha":"644c9afaccd478844dc6d04edfa78f461da1d38c","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054/commits","review_comments_url":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054/comments","review_comment_url":"https://api.github.com/repos/nuxeo/nuxeo/pulls/comments{/number}","comments_url":"https://api.github.com/repos/nuxeo/nuxeo/issues/2054/comments","statuses_url":"https://api.github.com/repos/nuxeo/nuxeo/statuses/9a40ae328ccdfe2a12b138df2d184a0348f5e4b3","head":{"label":"nuxeo:feature-NXP-24335-bulk-operation-part-1","ref":"feature-NXP-24335-bulk-operation-part-1","sha":"9a40ae328ccdfe2a12b138df2d184a0348f5e4b3","user":{"login":"nuxeo","id":460607,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ2MDYwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/460607?v=4","gravatar_id":"","url":"https://api.github.com/users/nuxeo","html_url":"https://github.com/nuxeo","followers_url":"https://api.github.com/users/nuxeo/followers","following_url":"https://api.github.com/users/nuxeo/following{/other_user}","gists_url":"https://api.github.com/users/nuxeo/gists{/gist_id}","starred_url":"https://api.github.com/users/nuxeo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nuxeo/subscriptions","organizations_url":"https://api.github.com/users/nuxeo/orgs","repos_url":"https://api.github.com/users/nuxeo/repos","events_url":"https://api.github.com/users/nuxeo/events{/privacy}","received_events_url":"https://api.github.com/users/nuxeo/received_events","type":"Organization","site_admin":false},"repo":{"id":2988101,"node_id":"MDEwOlJlcG9zaXRvcnkyOTg4MTAx","name":"nuxeo","full_name":"nuxeo/nuxeo","owner":{"login":"nuxeo","id":460607,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ2MDYwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/460607?v=4","gravatar_id":"","url":"https://api.github.com/users/nuxeo","html_url":"https://github.com/nuxeo","followers_url":"https://api.github.com/users/nuxeo/followers","following_url":"https://api.github.com/users/nuxeo/following{/other_user}","gists_url":"https://api.github.com/users/nuxeo/gists{/gist_id}","starred_url":"https://api.github.com/users/nuxeo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nuxeo/subscriptions","organizations_url":"https://api.github.com/users/nuxeo/orgs","repos_url":"https://api.github.com/users/nuxeo/repos","events_url":"https://api.github.com/users/nuxeo/events{/privacy}","received_events_url":"https://api.github.com/users/nuxeo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nuxeo/nuxeo","description":"Content management platform to build modern business applications","fork":false,"url":"https://api.github.com/repos/nuxeo/nuxeo","forks_url":"https://api.github.com/repos/nuxeo/nuxeo/forks","keys_url":"https://api.github.com/repos/nuxeo/nuxeo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nuxeo/nuxeo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nuxeo/nuxeo/teams","hooks_url":"https://api.github.com/repos/nuxeo/nuxeo/hooks","issue_events_url":"https://api.github.com/repos/nuxeo/nuxeo/issues/events{/number}","events_url":"https://api.github.com/repos/nuxeo/nuxeo/events","assignees_url":"https://api.github.com/repos/nuxeo/nuxeo/assignees{/user}","branches_url":"https://api.github.com/repos/nuxeo/nuxeo/branches{/branch}","tags_url":"https://api.github.com/repos/nuxeo/nuxeo/tags","blobs_url":"https://api.github.com/repos/nuxeo/nuxeo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nuxeo/nuxeo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nuxeo/nuxeo/git/refs{/sha}","trees_url":"https://api.github.com/repos/nuxeo/nuxeo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nuxeo/nuxeo/statuses/{sha}","languages_url":"https://api.github.com/repos/nuxeo/nuxeo/languages","stargazers_url":"https://api.github.com/repos/nuxeo/nuxeo/stargazers","contributors_url":"https://api.github.com/repos/nuxeo/nuxeo/contributors","subscribers_url":"https://api.github.com/repos/nuxeo/nuxeo/subscribers","subscription_url":"https://api.github.com/repos/nuxeo/nuxeo/subscription","commits_url":"https://api.github.com/repos/nuxeo/nuxeo/commits{/sha}","git_commits_url":"https://api.github.com/repos/nuxeo/nuxeo/git/commits{/sha}","comments_url":"https://api.github.com/repos/nuxeo/nuxeo/comments{/number}","issue_comment_url":"https://api.github.com/repos/nuxeo/nuxeo/issues/comments{/number}","contents_url":"https://api.github.com/repos/nuxeo/nuxeo/contents/{+path}","compare_url":"https://api.github.com/repos/nuxeo/nuxeo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nuxeo/nuxeo/merges","archive_url":"https://api.github.com/repos/nuxeo/nuxeo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nuxeo/nuxeo/downloads","issues_url":"https://api.github.com/repos/nuxeo/nuxeo/issues{/number}","pulls_url":"https://api.github.com/repos/nuxeo/nuxeo/pulls{/number}","milestones_url":"https://api.github.com/repos/nuxeo/nuxeo/milestones{/number}","notifications_url":"https://api.github.com/repos/nuxeo/nuxeo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nuxeo/nuxeo/labels{/name}","releases_url":"https://api.github.com/repos/nuxeo/nuxeo/releases{/id}","deployments_url":"https://api.github.com/repos/nuxeo/nuxeo/deployments","created_at":"2011-12-15T14:35:41Z","updated_at":"2018-06-06T12:47:48Z","pushed_at":"2018-06-07T10:04:46Z","git_url":"git://github.com/nuxeo/nuxeo.git","ssh_url":"git@github.com:nuxeo/nuxeo.git","clone_url":"https://github.com/nuxeo/nuxeo.git","svn_url":"https://github.com/nuxeo/nuxeo","homepage":"http://www.nuxeo.com","size":229245,"stargazers_count":222,"watchers_count":222,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":151,"mirror_url":null,"archived":false,"open_issues_count":13,"license":null,"forks":151,"open_issues":13,"watchers":222,"default_branch":"master"}},"base":{"label":"nuxeo:master","ref":"master","sha":"9fdaece1320f9e7cf6c0d2a9457cc96766609a21","user":{"login":"nuxeo","id":460607,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ2MDYwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/460607?v=4","gravatar_id":"","url":"https://api.github.com/users/nuxeo","html_url":"https://github.com/nuxeo","followers_url":"https://api.github.com/users/nuxeo/followers","following_url":"https://api.github.com/users/nuxeo/following{/other_user}","gists_url":"https://api.github.com/users/nuxeo/gists{/gist_id}","starred_url":"https://api.github.com/users/nuxeo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nuxeo/subscriptions","organizations_url":"https://api.github.com/users/nuxeo/orgs","repos_url":"https://api.github.com/users/nuxeo/repos","events_url":"https://api.github.com/users/nuxeo/events{/privacy}","received_events_url":"https://api.github.com/users/nuxeo/received_events","type":"Organization","site_admin":false},"repo":{"id":2988101,"node_id":"MDEwOlJlcG9zaXRvcnkyOTg4MTAx","name":"nuxeo","full_name":"nuxeo/nuxeo","owner":{"login":"nuxeo","id":460607,"node_id":"MDEyOk9yZ2FuaXphdGlvbjQ2MDYwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/460607?v=4","gravatar_id":"","url":"https://api.github.com/users/nuxeo","html_url":"https://github.com/nuxeo","followers_url":"https://api.github.com/users/nuxeo/followers","following_url":"https://api.github.com/users/nuxeo/following{/other_user}","gists_url":"https://api.github.com/users/nuxeo/gists{/gist_id}","starred_url":"https://api.github.com/users/nuxeo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nuxeo/subscriptions","organizations_url":"https://api.github.com/users/nuxeo/orgs","repos_url":"https://api.github.com/users/nuxeo/repos","events_url":"https://api.github.com/users/nuxeo/events{/privacy}","received_events_url":"https://api.github.com/users/nuxeo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/nuxeo/nuxeo","description":"Content management platform to build modern business applications","fork":false,"url":"https://api.github.com/repos/nuxeo/nuxeo","forks_url":"https://api.github.com/repos/nuxeo/nuxeo/forks","keys_url":"https://api.github.com/repos/nuxeo/nuxeo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nuxeo/nuxeo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nuxeo/nuxeo/teams","hooks_url":"https://api.github.com/repos/nuxeo/nuxeo/hooks","issue_events_url":"https://api.github.com/repos/nuxeo/nuxeo/issues/events{/number}","events_url":"https://api.github.com/repos/nuxeo/nuxeo/events","assignees_url":"https://api.github.com/repos/nuxeo/nuxeo/assignees{/user}","branches_url":"https://api.github.com/repos/nuxeo/nuxeo/branches{/branch}","tags_url":"https://api.github.com/repos/nuxeo/nuxeo/tags","blobs_url":"https://api.github.com/repos/nuxeo/nuxeo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nuxeo/nuxeo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nuxeo/nuxeo/git/refs{/sha}","trees_url":"https://api.github.com/repos/nuxeo/nuxeo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nuxeo/nuxeo/statuses/{sha}","languages_url":"https://api.github.com/repos/nuxeo/nuxeo/languages","stargazers_url":"https://api.github.com/repos/nuxeo/nuxeo/stargazers","contributors_url":"https://api.github.com/repos/nuxeo/nuxeo/contributors","subscribers_url":"https://api.github.com/repos/nuxeo/nuxeo/subscribers","subscription_url":"https://api.github.com/repos/nuxeo/nuxeo/subscription","commits_url":"https://api.github.com/repos/nuxeo/nuxeo/commits{/sha}","git_commits_url":"https://api.github.com/repos/nuxeo/nuxeo/git/commits{/sha}","comments_url":"https://api.github.com/repos/nuxeo/nuxeo/comments{/number}","issue_comment_url":"https://api.github.com/repos/nuxeo/nuxeo/issues/comments{/number}","contents_url":"https://api.github.com/repos/nuxeo/nuxeo/contents/{+path}","compare_url":"https://api.github.com/repos/nuxeo/nuxeo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nuxeo/nuxeo/merges","archive_url":"https://api.github.com/repos/nuxeo/nuxeo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nuxeo/nuxeo/downloads","issues_url":"https://api.github.com/repos/nuxeo/nuxeo/issues{/number}","pulls_url":"https://api.github.com/repos/nuxeo/nuxeo/pulls{/number}","milestones_url":"https://api.github.com/repos/nuxeo/nuxeo/milestones{/number}","notifications_url":"https://api.github.com/repos/nuxeo/nuxeo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nuxeo/nuxeo/labels{/name}","releases_url":"https://api.github.com/repos/nuxeo/nuxeo/releases{/id}","deployments_url":"https://api.github.com/repos/nuxeo/nuxeo/deployments","created_at":"2011-12-15T14:35:41Z","updated_at":"2018-06-06T12:47:48Z","pushed_at":"2018-06-07T10:04:46Z","git_url":"git://github.com/nuxeo/nuxeo.git","ssh_url":"git@github.com:nuxeo/nuxeo.git","clone_url":"https://github.com/nuxeo/nuxeo.git","svn_url":"https://github.com/nuxeo/nuxeo","homepage":"http://www.nuxeo.com","size":229245,"stargazers_count":222,"watchers_count":222,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":151,"mirror_url":null,"archived":false,"open_issues_count":13,"license":null,"forks":151,"open_issues":13,"watchers":222,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054"},"html":{"href":"https://github.com/nuxeo/nuxeo/pull/2054"},"issue":{"href":"https://api.github.com/repos/nuxeo/nuxeo/issues/2054"},"comments":{"href":"https://api.github.com/repos/nuxeo/nuxeo/issues/2054/comments"},"review_comments":{"href":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054/comments"},"review_comment":{"href":"https://api.github.com/repos/nuxeo/nuxeo/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/nuxeo/nuxeo/pulls/2054/commits"},"statuses":{"href":"https://api.github.com/repos/nuxeo/nuxeo/statuses/9a40ae328ccdfe2a12b138df2d184a0348f5e4b3"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"bdelbosc"}}