{"action":"created","comment":{"url":"https://api.github.com/repos/twitter/heron/pulls/comments/116068061","pull_request_review_id":37648509,"id":116068061,"diff_hunk":"@@ -0,0 +1,298 @@\n+// Copyright 2016 Twitter. All rights reserved.\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+package com.twitter.heron.ckptmgr;\n+\n+import java.io.IOException;\n+import java.nio.channels.SocketChannel;\n+import java.util.logging.Level;\n+import java.util.logging.Logger;\n+\n+import com.google.protobuf.ByteString;\n+import com.google.protobuf.Message;\n+\n+import com.twitter.heron.common.basics.NIOLooper;\n+import com.twitter.heron.common.network.HeronServer;\n+import com.twitter.heron.common.network.HeronSocketOptions;\n+import com.twitter.heron.common.network.REQID;\n+import com.twitter.heron.proto.ckptmgr.CheckpointManager;\n+import com.twitter.heron.proto.system.Common;\n+import com.twitter.heron.spi.statefulstorage.Checkpoint;\n+import com.twitter.heron.spi.statefulstorage.IStatefulStorage;\n+import com.twitter.heron.spi.statefulstorage.StatefulStorageException;\n+\n+public class CheckpointManagerServer extends HeronServer {\n+  private static final Logger LOG = Logger.getLogger(CheckpointManagerServer.class.getName());\n+\n+  private final String topologyName;\n+  private final String topologyId;\n+  private final String checkpointMgrId;\n+  private final IStatefulStorage checkpointsBackend;\n+\n+  private SocketChannel connection;\n+\n+  public CheckpointManagerServer(\n+      String topologyName, String topologyId, String checkpointMgrId,\n+      IStatefulStorage checkpointsBackend, NIOLooper looper, String host,\n+      int port, HeronSocketOptions options) {\n+    super(looper, host, port, options);\n+\n+    this.topologyName = topologyName;\n+    this.topologyId = topologyId;\n+    this.checkpointMgrId = checkpointMgrId;\n+    this.checkpointsBackend = checkpointsBackend;\n+\n+    this.connection = null;\n+\n+    registerInitialization();\n+  }\n+\n+  private void registerInitialization() {\n+    registerOnRequest(CheckpointManager.RegisterStMgrRequest.newBuilder());\n+\n+    registerOnRequest(CheckpointManager.RegisterTMasterRequest.newBuilder());\n+\n+    registerOnRequest(CheckpointManager.SaveInstanceStateRequest.newBuilder());\n+\n+    registerOnRequest(CheckpointManager.GetInstanceStateRequest.newBuilder());\n+\n+    registerOnRequest(CheckpointManager.CleanStatefulCheckpointRequest.newBuilder());\n+  }\n+\n+  @Override\n+  public void onConnect(SocketChannel channel) {\n+    LOG.info(\"Got a new connection from host:port \"\n+        + channel.socket().getRemoteSocketAddress());\n+  }\n+\n+  @Override\n+  public void onRequest(REQID rid, SocketChannel channel, Message request) {\n+    if (request instanceof CheckpointManager.RegisterStMgrRequest) {\n+      handleStMgrRegisterRequest(rid, channel, (CheckpointManager.RegisterStMgrRequest) request);\n+    } else if (request instanceof CheckpointManager.RegisterTMasterRequest) {\n+      handleTMasterRegisterRequest(rid, channel,\n+                                   (CheckpointManager.RegisterTMasterRequest) request);\n+    } else if (request instanceof CheckpointManager.SaveInstanceStateRequest) {\n+      handleSaveInstanceStateRequest(\n+          rid, channel, (CheckpointManager.SaveInstanceStateRequest) request);\n+    } else if (request instanceof CheckpointManager.GetInstanceStateRequest) {\n+      handleGetInstanceStateRequest(\n+          rid, channel, (CheckpointManager.GetInstanceStateRequest) request);\n+    } else if (request instanceof CheckpointManager.CleanStatefulCheckpointRequest) {\n+      handleCleanStatefulCheckpointRequest(\n+          rid, channel, (CheckpointManager.CleanStatefulCheckpointRequest) request);\n+    } else {\n+      LOG.severe(\"Unknown kind of request: \" + request.getClass().getName());\n+    }\n+  }\n+\n+  protected void handleCleanStatefulCheckpointRequest(\n+      REQID rid,\n+      SocketChannel channel,\n+      CheckpointManager.CleanStatefulCheckpointRequest request\n+  ) {\n+    LOG.info(\"Got a clean request from \" + request.toString() + \" host:port \"\n+        + channel.socket().getRemoteSocketAddress());\n+\n+    boolean deleteAll = request.hasCleanAllCheckpoints() && request.getCleanAllCheckpoints();\n+    Common.StatusCode statusCode = Common.StatusCode.OK;\n+\n+    try {\n+      checkpointsBackend.dispose(topologyName,\n+                                 request.getOldestCheckpointPreserved(), deleteAll);\n+      LOG.info(\"Dispose checkpoint successful\");\n+    } catch (StatefulStorageException e) {\n+      LOG.info(\"Dispose checkpoint failed with error \" + e);\n+      statusCode = Common.StatusCode.NOTOK;\n+    }\n+\n+    CheckpointManager.CleanStatefulCheckpointResponse.Builder responseBuilder =\n+        CheckpointManager.CleanStatefulCheckpointResponse.newBuilder();\n+    responseBuilder.setStatus(Common.Status.newBuilder().setStatus(statusCode));\n+\n+    sendResponse(rid, channel, responseBuilder.build());\n+  }\n+\n+  protected void handleTMasterRegisterRequest(\n+      REQID rid,\n+      SocketChannel channel,\n+      CheckpointManager.RegisterTMasterRequest request\n+  ) {\n+    LOG.info(\"Got a register request from TMaster host:port \"\n+        + channel.socket().getRemoteSocketAddress());\n+\n+    CheckpointManager.RegisterTMasterResponse.Builder responseBuilder =\n+        CheckpointManager.RegisterTMasterResponse.newBuilder();\n+\n+    if (!request.getTopologyName().equals(topologyName)) {\n+      LOG.severe(\"The register message was from a different topology: \"\n+          + request.getTopologyName());\n+      responseBuilder.setStatus(Common.Status.newBuilder().setStatus(Common.StatusCode.NOTOK));\n+    } else if (!request.getTopologyId().equals(topologyId)) {\n+      LOG.severe(\"The register message was from a different topology id: \"\n+          + request.getTopologyName());\n+      responseBuilder.setStatus(Common.Status.newBuilder().setStatus(Common.StatusCode.NOTOK));\n+    } else if (connection != null) {\n+      // TODO(mfu): Should we do this?\n+      LOG.warning(\"We already have an active connection from the tmaster \"\n+          + \"Closing existing connection...\");\n+\n+      try {\n+        connection.close();\n+      } catch (IOException e) {\n+        LOG.warning(\"Failed to close connection from: \"\n+                  + connection.socket().getRemoteSocketAddress());\n+      }\n+\n+      connection = null;\n+      responseBuilder.setStatus(Common.Status.newBuilder().setStatus(Common.StatusCode.NOTOK));\n+    } else {\n+      connection = channel;\n+      responseBuilder.setStatus(Common.Status.newBuilder().setStatus(Common.StatusCode.OK));\n+    }\n+\n+    sendResponse(rid, channel, responseBuilder.build());\n+  }\n+\n+  protected void handleStMgrRegisterRequest(","path":"heron/ckptmgr/src/java/com/twitter/heron/ckptmgr/CheckpointManagerServer.java","position":168,"original_position":168,"commit_id":"f18f8b9ab9d20370714e8eb0e23ec26ca363fd8f","original_commit_id":"f18f8b9ab9d20370714e8eb0e23ec26ca363fd8f","user":{"login":"billonahill","id":23758,"avatar_url":"https://avatars0.githubusercontent.com/u/23758?v=3","gravatar_id":"","url":"https://api.github.com/users/billonahill","html_url":"https://github.com/billonahill","followers_url":"https://api.github.com/users/billonahill/followers","following_url":"https://api.github.com/users/billonahill/following{/other_user}","gists_url":"https://api.github.com/users/billonahill/gists{/gist_id}","starred_url":"https://api.github.com/users/billonahill/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/billonahill/subscriptions","organizations_url":"https://api.github.com/users/billonahill/orgs","repos_url":"https://api.github.com/users/billonahill/repos","events_url":"https://api.github.com/users/billonahill/events{/privacy}","received_events_url":"https://api.github.com/users/billonahill/received_events","type":"User","site_admin":false},"body":"How is the implementation of this method different from handleTMasterRegisterRequest? They appear to be duplicates.","created_at":"2017-05-11T18:29:46Z","updated_at":"2017-05-11T18:42:26Z","html_url":"https://github.com/twitter/heron/pull/1831#discussion_r116068061","pull_request_url":"https://api.github.com/repos/twitter/heron/pulls/1831","_links":{"self":{"href":"https://api.github.com/repos/twitter/heron/pulls/comments/116068061"},"html":{"href":"https://github.com/twitter/heron/pull/1831#discussion_r116068061"},"pull_request":{"href":"https://api.github.com/repos/twitter/heron/pulls/1831"}}},"pull_request":{"url":"https://api.github.com/repos/twitter/heron/pulls/1831","id":118881330,"html_url":"https://github.com/twitter/heron/pull/1831","diff_url":"https://github.com/twitter/heron/pull/1831.diff","patch_url":"https://github.com/twitter/heron/pull/1831.patch","issue_url":"https://api.github.com/repos/twitter/heron/issues/1831","number":1831,"state":"open","locked":false,"title":"Added Checkpoint Manager for stateful topologies","user":{"login":"srkukarni","id":2530234,"avatar_url":"https://avatars3.githubusercontent.com/u/2530234?v=3","gravatar_id":"","url":"https://api.github.com/users/srkukarni","html_url":"https://github.com/srkukarni","followers_url":"https://api.github.com/users/srkukarni/followers","following_url":"https://api.github.com/users/srkukarni/following{/other_user}","gists_url":"https://api.github.com/users/srkukarni/gists{/gist_id}","starred_url":"https://api.github.com/users/srkukarni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/srkukarni/subscriptions","organizations_url":"https://api.github.com/users/srkukarni/orgs","repos_url":"https://api.github.com/users/srkukarni/repos","events_url":"https://api.github.com/users/srkukarni/events{/privacy}","received_events_url":"https://api.github.com/users/srkukarni/received_events","type":"User","site_admin":false},"body":"","created_at":"2017-05-04T00:23:16Z","updated_at":"2017-05-11T18:42:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"601f173163a12f7aad4f64a6e7f3b570af3637a8","assignee":null,"assignees":[],"requested_reviewers":[{"login":"nlu90","id":16407807,"avatar_url":"https://avatars3.githubusercontent.com/u/16407807?v=3","gravatar_id":"","url":"https://api.github.com/users/nlu90","html_url":"https://github.com/nlu90","followers_url":"https://api.github.com/users/nlu90/followers","following_url":"https://api.github.com/users/nlu90/following{/other_user}","gists_url":"https://api.github.com/users/nlu90/gists{/gist_id}","starred_url":"https://api.github.com/users/nlu90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nlu90/subscriptions","organizations_url":"https://api.github.com/users/nlu90/orgs","repos_url":"https://api.github.com/users/nlu90/repos","events_url":"https://api.github.com/users/nlu90/events{/privacy}","received_events_url":"https://api.github.com/users/nlu90/received_events","type":"User","site_admin":false},{"login":"maosongfu","id":3028698,"avatar_url":"https://avatars1.githubusercontent.com/u/3028698?v=3","gravatar_id":"","url":"https://api.github.com/users/maosongfu","html_url":"https://github.com/maosongfu","followers_url":"https://api.github.com/users/maosongfu/followers","following_url":"https://api.github.com/users/maosongfu/following{/other_user}","gists_url":"https://api.github.com/users/maosongfu/gists{/gist_id}","starred_url":"https://api.github.com/users/maosongfu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maosongfu/subscriptions","organizations_url":"https://api.github.com/users/maosongfu/orgs","repos_url":"https://api.github.com/users/maosongfu/repos","events_url":"https://api.github.com/users/maosongfu/events{/privacy}","received_events_url":"https://api.github.com/users/maosongfu/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/twitter/heron/pulls/1831/commits","review_comments_url":"https://api.github.com/repos/twitter/heron/pulls/1831/comments","review_comment_url":"https://api.github.com/repos/twitter/heron/pulls/comments{/number}","comments_url":"https://api.github.com/repos/twitter/heron/issues/1831/comments","statuses_url":"https://api.github.com/repos/twitter/heron/statuses/f18f8b9ab9d20370714e8eb0e23ec26ca363fd8f","head":{"label":"streamlio:sanjeevk/ext1_ckptmgr","ref":"sanjeevk/ext1_ckptmgr","sha":"f18f8b9ab9d20370714e8eb0e23ec26ca363fd8f","user":{"login":"streamlio","id":21353322,"avatar_url":"https://avatars1.githubusercontent.com/u/21353322?v=3","gravatar_id":"","url":"https://api.github.com/users/streamlio","html_url":"https://github.com/streamlio","followers_url":"https://api.github.com/users/streamlio/followers","following_url":"https://api.github.com/users/streamlio/following{/other_user}","gists_url":"https://api.github.com/users/streamlio/gists{/gist_id}","starred_url":"https://api.github.com/users/streamlio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/streamlio/subscriptions","organizations_url":"https://api.github.com/users/streamlio/orgs","repos_url":"https://api.github.com/users/streamlio/repos","events_url":"https://api.github.com/users/streamlio/events{/privacy}","received_events_url":"https://api.github.com/users/streamlio/received_events","type":"Organization","site_admin":false},"repo":{"id":67003283,"name":"heron","full_name":"streamlio/heron","owner":{"login":"streamlio","id":21353322,"avatar_url":"https://avatars1.githubusercontent.com/u/21353322?v=3","gravatar_id":"","url":"https://api.github.com/users/streamlio","html_url":"https://github.com/streamlio","followers_url":"https://api.github.com/users/streamlio/followers","following_url":"https://api.github.com/users/streamlio/following{/other_user}","gists_url":"https://api.github.com/users/streamlio/gists{/gist_id}","starred_url":"https://api.github.com/users/streamlio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/streamlio/subscriptions","organizations_url":"https://api.github.com/users/streamlio/orgs","repos_url":"https://api.github.com/users/streamlio/repos","events_url":"https://api.github.com/users/streamlio/events{/privacy}","received_events_url":"https://api.github.com/users/streamlio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/streamlio/heron","description":"Heron is a realtime, distributed, fault-tolerant stream processing engine from Twitter","fork":true,"url":"https://api.github.com/repos/streamlio/heron","forks_url":"https://api.github.com/repos/streamlio/heron/forks","keys_url":"https://api.github.com/repos/streamlio/heron/keys{/key_id}","collaborators_url":"https://api.github.com/repos/streamlio/heron/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/streamlio/heron/teams","hooks_url":"https://api.github.com/repos/streamlio/heron/hooks","issue_events_url":"https://api.github.com/repos/streamlio/heron/issues/events{/number}","events_url":"https://api.github.com/repos/streamlio/heron/events","assignees_url":"https://api.github.com/repos/streamlio/heron/assignees{/user}","branches_url":"https://api.github.com/repos/streamlio/heron/branches{/branch}","tags_url":"https://api.github.com/repos/streamlio/heron/tags","blobs_url":"https://api.github.com/repos/streamlio/heron/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/streamlio/heron/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/streamlio/heron/git/refs{/sha}","trees_url":"https://api.github.com/repos/streamlio/heron/git/trees{/sha}","statuses_url":"https://api.github.com/repos/streamlio/heron/statuses/{sha}","languages_url":"https://api.github.com/repos/streamlio/heron/languages","stargazers_url":"https://api.github.com/repos/streamlio/heron/stargazers","contributors_url":"https://api.github.com/repos/streamlio/heron/contributors","subscribers_url":"https://api.github.com/repos/streamlio/heron/subscribers","subscription_url":"https://api.github.com/repos/streamlio/heron/subscription","commits_url":"https://api.github.com/repos/streamlio/heron/commits{/sha}","git_commits_url":"https://api.github.com/repos/streamlio/heron/git/commits{/sha}","comments_url":"https://api.github.com/repos/streamlio/heron/comments{/number}","issue_comment_url":"https://api.github.com/repos/streamlio/heron/issues/comments{/number}","contents_url":"https://api.github.com/repos/streamlio/heron/contents/{+path}","compare_url":"https://api.github.com/repos/streamlio/heron/compare/{base}...{head}","merges_url":"https://api.github.com/repos/streamlio/heron/merges","archive_url":"https://api.github.com/repos/streamlio/heron/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/streamlio/heron/downloads","issues_url":"https://api.github.com/repos/streamlio/heron/issues{/number}","pulls_url":"https://api.github.com/repos/streamlio/heron/pulls{/number}","milestones_url":"https://api.github.com/repos/streamlio/heron/milestones{/number}","notifications_url":"https://api.github.com/repos/streamlio/heron/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/streamlio/heron/labels{/name}","releases_url":"https://api.github.com/repos/streamlio/heron/releases{/id}","deployments_url":"https://api.github.com/repos/streamlio/heron/deployments","created_at":"2016-08-31T04:28:57Z","updated_at":"2016-08-31T04:29:01Z","pushed_at":"2017-05-11T17:57:15Z","git_url":"git://github.com/streamlio/heron.git","ssh_url":"git@github.com:streamlio/heron.git","clone_url":"https://github.com/streamlio/heron.git","svn_url":"https://github.com/streamlio/heron","homepage":"http://heronstreaming.io","size":123882,"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,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"twitter:master","ref":"master","sha":"fb9193506d287ad6574c5bbb71a448eb03691a0b","user":{"login":"twitter","id":50278,"avatar_url":"https://avatars2.githubusercontent.com/u/50278?v=3","gravatar_id":"","url":"https://api.github.com/users/twitter","html_url":"https://github.com/twitter","followers_url":"https://api.github.com/users/twitter/followers","following_url":"https://api.github.com/users/twitter/following{/other_user}","gists_url":"https://api.github.com/users/twitter/gists{/gist_id}","starred_url":"https://api.github.com/users/twitter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/twitter/subscriptions","organizations_url":"https://api.github.com/users/twitter/orgs","repos_url":"https://api.github.com/users/twitter/repos","events_url":"https://api.github.com/users/twitter/events{/privacy}","received_events_url":"https://api.github.com/users/twitter/received_events","type":"Organization","site_admin":false},"repo":{"id":43158694,"name":"heron","full_name":"twitter/heron","owner":{"login":"twitter","id":50278,"avatar_url":"https://avatars2.githubusercontent.com/u/50278?v=3","gravatar_id":"","url":"https://api.github.com/users/twitter","html_url":"https://github.com/twitter","followers_url":"https://api.github.com/users/twitter/followers","following_url":"https://api.github.com/users/twitter/following{/other_user}","gists_url":"https://api.github.com/users/twitter/gists{/gist_id}","starred_url":"https://api.github.com/users/twitter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/twitter/subscriptions","organizations_url":"https://api.github.com/users/twitter/orgs","repos_url":"https://api.github.com/users/twitter/repos","events_url":"https://api.github.com/users/twitter/events{/privacy}","received_events_url":"https://api.github.com/users/twitter/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/twitter/heron","description":"Heron is a realtime, distributed, fault-tolerant stream processing engine from Twitter","fork":false,"url":"https://api.github.com/repos/twitter/heron","forks_url":"https://api.github.com/repos/twitter/heron/forks","keys_url":"https://api.github.com/repos/twitter/heron/keys{/key_id}","collaborators_url":"https://api.github.com/repos/twitter/heron/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/twitter/heron/teams","hooks_url":"https://api.github.com/repos/twitter/heron/hooks","issue_events_url":"https://api.github.com/repos/twitter/heron/issues/events{/number}","events_url":"https://api.github.com/repos/twitter/heron/events","assignees_url":"https://api.github.com/repos/twitter/heron/assignees{/user}","branches_url":"https://api.github.com/repos/twitter/heron/branches{/branch}","tags_url":"https://api.github.com/repos/twitter/heron/tags","blobs_url":"https://api.github.com/repos/twitter/heron/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/twitter/heron/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/twitter/heron/git/refs{/sha}","trees_url":"https://api.github.com/repos/twitter/heron/git/trees{/sha}","statuses_url":"https://api.github.com/repos/twitter/heron/statuses/{sha}","languages_url":"https://api.github.com/repos/twitter/heron/languages","stargazers_url":"https://api.github.com/repos/twitter/heron/stargazers","contributors_url":"https://api.github.com/repos/twitter/heron/contributors","subscribers_url":"https://api.github.com/repos/twitter/heron/subscribers","subscription_url":"https://api.github.com/repos/twitter/heron/subscription","commits_url":"https://api.github.com/repos/twitter/heron/commits{/sha}","git_commits_url":"https://api.github.com/repos/twitter/heron/git/commits{/sha}","comments_url":"https://api.github.com/repos/twitter/heron/comments{/number}","issue_comment_url":"https://api.github.com/repos/twitter/heron/issues/comments{/number}","contents_url":"https://api.github.com/repos/twitter/heron/contents/{+path}","compare_url":"https://api.github.com/repos/twitter/heron/compare/{base}...{head}","merges_url":"https://api.github.com/repos/twitter/heron/merges","archive_url":"https://api.github.com/repos/twitter/heron/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/twitter/heron/downloads","issues_url":"https://api.github.com/repos/twitter/heron/issues{/number}","pulls_url":"https://api.github.com/repos/twitter/heron/pulls{/number}","milestones_url":"https://api.github.com/repos/twitter/heron/milestones{/number}","notifications_url":"https://api.github.com/repos/twitter/heron/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/twitter/heron/labels{/name}","releases_url":"https://api.github.com/repos/twitter/heron/releases{/id}","deployments_url":"https://api.github.com/repos/twitter/heron/deployments","created_at":"2015-09-25T16:09:24Z","updated_at":"2017-05-11T17:29:00Z","pushed_at":"2017-05-11T18:29:25Z","git_url":"git://github.com/twitter/heron.git","ssh_url":"git@github.com:twitter/heron.git","clone_url":"https://github.com/twitter/heron.git","svn_url":"https://github.com/twitter/heron","homepage":"http://heronstreaming.io","size":130455,"stargazers_count":2698,"watchers_count":2698,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":472,"mirror_url":null,"open_issues_count":256,"forks":472,"open_issues":256,"watchers":2698,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/twitter/heron/pulls/1831"},"html":{"href":"https://github.com/twitter/heron/pull/1831"},"issue":{"href":"https://api.github.com/repos/twitter/heron/issues/1831"},"comments":{"href":"https://api.github.com/repos/twitter/heron/issues/1831/comments"},"review_comments":{"href":"https://api.github.com/repos/twitter/heron/pulls/1831/comments"},"review_comment":{"href":"https://api.github.com/repos/twitter/heron/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/twitter/heron/pulls/1831/commits"},"statuses":{"href":"https://api.github.com/repos/twitter/heron/statuses/f18f8b9ab9d20370714e8eb0e23ec26ca363fd8f"}}}}
{"actor":{"display_login":"billonahill"}}