{"action":"created","comment":{"url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/comments/99745736","pull_request_review_id":20430272,"id":99745736,"diff_hunk":"@@ -0,0 +1,482 @@\n+/*\n+ * Copyright 2016 Google Inc. 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+\n+package com.google.cloud.pubsub.spi.v1;\n+\n+import com.google.api.gax.grpc.FlowController;\n+import com.google.api.stats.Distribution;\n+import com.google.cloud.Clock;\n+import com.google.cloud.pubsub.spi.v1.MessageReceiver.AckReply;\n+import com.google.common.annotations.VisibleForTesting;\n+import com.google.common.collect.Lists;\n+import com.google.common.primitives.Ints;\n+import com.google.common.util.concurrent.FutureCallback;\n+import com.google.common.util.concurrent.Futures;\n+import com.google.common.util.concurrent.SettableFuture;\n+import com.google.pubsub.v1.PubsubMessage;\n+import com.google.pubsub.v1.ReceivedMessage;\n+import java.util.ArrayList;\n+import java.util.Collections;\n+import java.util.HashSet;\n+import java.util.Iterator;\n+import java.util.List;\n+import java.util.PriorityQueue;\n+import java.util.Set;\n+import java.util.concurrent.ScheduledExecutorService;\n+import java.util.concurrent.ScheduledFuture;\n+import java.util.concurrent.TimeUnit;\n+import java.util.concurrent.atomic.AtomicBoolean;\n+import java.util.concurrent.locks.Lock;\n+import java.util.concurrent.locks.ReentrantLock;\n+import org.joda.time.Duration;\n+import org.joda.time.Instant;\n+import org.joda.time.Interval;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+/**\n+ * Dispatches messages to a message receiver while handling the messages acking and lease\n+ * extensions.\n+ */\n+class MessageDispatcher {\n+  private static final Logger logger = LoggerFactory.getLogger(MessageDispatcher.class);\n+\n+  private static final int INITIAL_ACK_DEADLINE_EXTENSION_SECONDS = 2;\n+  @VisibleForTesting static final Duration PENDING_ACKS_SEND_DELAY = Duration.millis(100);\n+  private static final int MAX_ACK_DEADLINE_EXTENSION_SECS = 10 * 60; // 10m\n+\n+  private final ScheduledExecutorService executor;\n+  private final Clock clock;\n+\n+  private final Duration ackExpirationPadding;\n+  private final MessageReceiver receiver;\n+  private final AckProcessor ackProcessor;\n+\n+  private final FlowController flowController;\n+  private final MessagesWaiter messagesWaiter;\n+\n+  private final PriorityQueue<ExtensionJob> outstandingAckHandlers;\n+  private final Set<String> pendingAcks;\n+  private final Set<String> pendingNacks;\n+\n+  private final Lock alarmsLock;\n+  private int messageDeadlineSeconds;\n+  private ScheduledFuture<?> ackDeadlineExtensionAlarm;\n+  private Instant nextAckDeadlineExtensionAlarmTime;\n+  private ScheduledFuture<?> pendingAcksAlarm;\n+\n+  // To keep track of number of seconds the receiver takes to process messages.\n+  private final Distribution ackLatencyDistribution;\n+\n+  // ExtensionJob represents a group of {@code AckHandler}s that shares the same expiration.\n+  //\n+  // It is Comparable so that it may be put in a PriorityQueue.\n+  // For efficiency, it is also mutable, so great care should be taken to make sure\n+  // it is not modified while inside the queue.\n+  // The hashcode and equals methods are explicitly not implemented to discourage\n+  // the use of this class as keys in maps or similar containers.\n+  private static class ExtensionJob implements Comparable<ExtensionJob> {\n+    Instant expiration;\n+    int nextExtensionSeconds;\n+    ArrayList<AckHandler> ackHandlers;\n+\n+    ExtensionJob(\n+        Instant expiration, int initialAckDeadlineExtension, ArrayList<AckHandler> ackHandlers) {\n+      this.expiration = expiration;\n+      nextExtensionSeconds = initialAckDeadlineExtension;\n+      this.ackHandlers = ackHandlers;\n+    }\n+\n+    void extendExpiration(Instant now) {\n+      expiration = now.plus(Duration.standardSeconds(nextExtensionSeconds));\n+      nextExtensionSeconds = Math.min(2 * nextExtensionSeconds, MAX_ACK_DEADLINE_EXTENSION_SECS);\n+    }\n+\n+    @Override\n+    public int compareTo(ExtensionJob other) {\n+      return expiration.compareTo(other.expiration);\n+    }\n+\n+    public String toString() {\n+      ArrayList<String> ackIds = new ArrayList<>();\n+      for (AckHandler ah : ackHandlers) {\n+        ackIds.add(ah.ackId);\n+      }\n+      return String.format(\n+          \"ExtensionJob {expiration: %s, nextExtensionSeconds: %d, ackIds: %s}\",\n+          expiration, nextExtensionSeconds, ackIds);\n+    }\n+  }\n+\n+  /** Stores the data needed to asynchronously modify acknowledgement deadlines. */\n+  static class PendingModifyAckDeadline {\n+    final List<String> ackIds;\n+    final int deadlineExtensionSeconds;\n+\n+    PendingModifyAckDeadline(int deadlineExtensionSeconds) {\n+      this.ackIds = new ArrayList<String>();\n+      this.deadlineExtensionSeconds = deadlineExtensionSeconds;\n+    }\n+\n+    PendingModifyAckDeadline(String ackId, int deadlineExtensionSeconds) {\n+      this(deadlineExtensionSeconds);\n+      addAckId(ackId);\n+    }\n+\n+    public void addAckId(String ackId) {\n+      ackIds.add(ackId);\n+    }\n+\n+    public String toString() {\n+      return String.format(\n+          \"PendingModifyAckDeadline{extension: %d sec, ackIds: %s}\",\n+          deadlineExtensionSeconds, ackIds);\n+    }\n+  }\n+\n+  /**\n+   * Handles callbacks for acking/nacking messages from the {@link\n+   * com.google.cloud.pubsub.MessageReceiver}.\n+   */\n+  private class AckHandler implements FutureCallback<AckReply> {\n+    private final String ackId;\n+    private final int outstandingBytes;\n+    private final AtomicBoolean acked;\n+    private final Instant receivedTime;\n+\n+    AckHandler(String ackId, int outstandingBytes) {\n+      this.ackId = ackId;\n+      this.outstandingBytes = outstandingBytes;\n+      acked = new AtomicBoolean(false);\n+      receivedTime = new Instant(clock.millis());\n+    }\n+\n+    @Override\n+    public void onFailure(Throwable t) {\n+      logger.warn(\n+          \"MessageReceiver failed to processes ack ID: \" + ackId + \", the message will be nacked.\",\n+          t);\n+      synchronized (pendingNacks) {\n+        pendingNacks.add(ackId);\n+      }\n+      setupPendingAcksAlarm();\n+      flowController.release(1, outstandingBytes);\n+      messagesWaiter.incrementPendingMessages(-1);\n+    }\n+\n+    @Override\n+    public void onSuccess(AckReply reply) {\n+      acked.getAndSet(true);\n+      switch (reply) {\n+        case ACK:\n+          synchronized (pendingAcks) {\n+            pendingAcks.add(ackId);\n+          }\n+          setupPendingAcksAlarm();\n+          flowController.release(1, outstandingBytes);\n+          // Record the latency rounded to the next closest integer.\n+          ackLatencyDistribution.record(\n+              Ints.saturatedCast(\n+                  (long) Math.ceil((clock.millis() - receivedTime.getMillis()) / 1000D)));\n+          messagesWaiter.incrementPendingMessages(-1);\n+          return;\n+        case NACK:\n+          synchronized (pendingNacks) {\n+            pendingNacks.add(ackId);\n+          }\n+          setupPendingAcksAlarm();\n+          flowController.release(1, outstandingBytes);\n+          messagesWaiter.incrementPendingMessages(-1);\n+          return;\n+        default:\n+          throw new IllegalArgumentException(String.format(\"AckReply: %s not supported\", reply));\n+      }\n+    }\n+  }\n+\n+  public interface AckProcessor {\n+    void sendAckOperations(\n+        List<String> acksToSend, List<PendingModifyAckDeadline> ackDeadlineExtensions);\n+  }\n+\n+  MessageDispatcher(\n+      MessageReceiver receiver,\n+      AckProcessor ackProcessor,\n+      Duration ackExpirationPadding,\n+      Distribution ackLatencyDistribution,\n+      FlowController flowController,\n+      ScheduledExecutorService executor,\n+      Clock clock) {\n+    this.executor = executor;\n+    this.ackExpirationPadding = ackExpirationPadding;\n+    this.receiver = receiver;\n+    this.ackProcessor = ackProcessor;\n+    this.flowController = flowController;\n+    outstandingAckHandlers = new PriorityQueue<>();\n+    pendingAcks = new HashSet<>();\n+    pendingNacks = new HashSet<>();\n+    // 601 buckets of 1s resolution from 0s to MAX_ACK_DEADLINE_SECONDS\n+    this.ackLatencyDistribution = ackLatencyDistribution;\n+    alarmsLock = new ReentrantLock();\n+    nextAckDeadlineExtensionAlarmTime = new Instant(Long.MAX_VALUE);\n+    messagesWaiter = new MessagesWaiter();\n+    this.clock = clock;\n+  }\n+\n+  public void stop() {\n+    messagesWaiter.waitNoMessages();\n+    alarmsLock.lock();\n+    try {\n+      if (ackDeadlineExtensionAlarm != null) {\n+        ackDeadlineExtensionAlarm.cancel(true);\n+        ackDeadlineExtensionAlarm = null;\n+      }\n+    } finally {\n+      alarmsLock.unlock();\n+    }\n+    processOutstandingAckOperations();\n+  }\n+\n+  public void setMessageDeadlineSeconds(int messageDeadlineSeconds) {\n+    this.messageDeadlineSeconds = messageDeadlineSeconds;\n+  }\n+\n+  public int getMessageDeadlineSeconds() {\n+    return messageDeadlineSeconds;\n+  }\n+\n+  public void processReceivedMessages(List<com.google.pubsub.v1.ReceivedMessage> responseMessages) {\n+    int receivedMessagesCount = responseMessages.size();\n+    if (receivedMessagesCount == 0) {\n+      return;\n+    }\n+    Instant now = new Instant(clock.millis());\n+    int totalByteCount = 0;\n+    final ArrayList<AckHandler> ackHandlers = new ArrayList<>(responseMessages.size());\n+    for (ReceivedMessage pubsubMessage : responseMessages) {\n+      int messageSize = pubsubMessage.getMessage().getSerializedSize();\n+      totalByteCount += messageSize;\n+      ackHandlers.add(new AckHandler(pubsubMessage.getAckId(), messageSize));\n+    }\n+    Instant expiration = now.plus(messageDeadlineSeconds * 1000);\n+    logger.debug(\"Received {} messages at {}\", responseMessages.size(), now);\n+\n+    messagesWaiter.incrementPendingMessages(responseMessages.size());\n+    Iterator<AckHandler> acksIterator = ackHandlers.iterator();\n+    for (ReceivedMessage userMessage : responseMessages) {\n+      final PubsubMessage message = userMessage.getMessage();\n+      final AckHandler ackHandler = acksIterator.next();\n+      final SettableFuture<AckReply> response = SettableFuture.create();\n+      Futures.addCallback(response, ackHandler);\n+      executor.submit(\n+          new Runnable() {\n+            @Override\n+            public void run() {\n+              receiver.receiveMessage(message, response);\n+            }\n+          });\n+    }\n+\n+    synchronized (outstandingAckHandlers) {\n+      outstandingAckHandlers.add(\n+          new ExtensionJob(expiration, INITIAL_ACK_DEADLINE_EXTENSION_SECONDS, ackHandlers));\n+    }\n+    setupNextAckDeadlineExtensionAlarm(expiration);\n+\n+    try {\n+      flowController.reserve(receivedMessagesCount, totalByteCount);\n+    } catch (FlowController.FlowControlException unexpectedException) {\n+      throw new IllegalStateException(\"Flow control unexpected exception\", unexpectedException);\n+    }\n+  }\n+\n+  private void setupPendingAcksAlarm() {\n+    alarmsLock.lock();\n+    try {\n+      if (pendingAcksAlarm == null) {\n+        pendingAcksAlarm =\n+            executor.schedule(\n+                new Runnable() {\n+                  @Override\n+                  public void run() {\n+                    alarmsLock.lock();\n+                    try {\n+                      pendingAcksAlarm = null;\n+                    } finally {\n+                      alarmsLock.unlock();\n+                    }\n+                    processOutstandingAckOperations();\n+                  }\n+                },\n+                PENDING_ACKS_SEND_DELAY.getMillis(),\n+                TimeUnit.MILLISECONDS);\n+      }\n+    } finally {\n+      alarmsLock.unlock();\n+    }\n+  }\n+\n+  private class AckDeadlineAlarm implements Runnable {\n+    @Override\n+    public void run() {","path":"google-cloud-pubsub/src/main/java/com/google/cloud/pubsub/spi/v1/MessageDispatcher.java","position":334,"original_position":334,"commit_id":"374210e0cccdba6c15d4f8d889efe2ec3927b586","original_commit_id":"374210e0cccdba6c15d4f8d889efe2ec3927b586","user":{"login":"codacy-bot","id":19940114,"avatar_url":"https://avatars.githubusercontent.com/u/19940114?v=3","gravatar_id":"","url":"https://api.github.com/users/codacy-bot","html_url":"https://github.com/codacy-bot","followers_url":"https://api.github.com/users/codacy-bot/followers","following_url":"https://api.github.com/users/codacy-bot/following{/other_user}","gists_url":"https://api.github.com/users/codacy-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/codacy-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codacy-bot/subscriptions","organizations_url":"https://api.github.com/users/codacy-bot/orgs","repos_url":"https://api.github.com/users/codacy-bot/repos","events_url":"https://api.github.com/users/codacy-bot/events{/privacy}","received_events_url":"https://api.github.com/users/codacy-bot/received_events","type":"User","site_admin":false},"body":"![Codacy](https://www.codacy.com/assets/images/favicon.png) Issue found: [The method run() has an NPath complexity of 336](https://www.codacy.com/app/mziccard/google-cloud-java/pullRequest?prid=506977)","created_at":"2017-02-07T04:54:51Z","updated_at":"2017-02-07T04:54:51Z","html_url":"https://github.com/GoogleCloudPlatform/google-cloud-java/pull/1593#discussion_r99745736","pull_request_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593","_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/comments/99745736"},"html":{"href":"https://github.com/GoogleCloudPlatform/google-cloud-java/pull/1593#discussion_r99745736"},"pull_request":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593"}}},"pull_request":{"url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593","id":104936736,"html_url":"https://github.com/GoogleCloudPlatform/google-cloud-java/pull/1593","diff_url":"https://github.com/GoogleCloudPlatform/google-cloud-java/pull/1593.diff","patch_url":"https://github.com/GoogleCloudPlatform/google-cloud-java/pull/1593.patch","issue_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/issues/1593","number":1593,"state":"open","locked":false,"title":"merge pubsub-hp into master","user":{"login":"pongad","id":1617025,"avatar_url":"https://avatars.githubusercontent.com/u/1617025?v=3","gravatar_id":"","url":"https://api.github.com/users/pongad","html_url":"https://github.com/pongad","followers_url":"https://api.github.com/users/pongad/followers","following_url":"https://api.github.com/users/pongad/following{/other_user}","gists_url":"https://api.github.com/users/pongad/gists{/gist_id}","starred_url":"https://api.github.com/users/pongad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pongad/subscriptions","organizations_url":"https://api.github.com/users/pongad/orgs","repos_url":"https://api.github.com/users/pongad/repos","events_url":"https://api.github.com/users/pongad/events{/privacy}","received_events_url":"https://api.github.com/users/pongad/received_events","type":"User","site_admin":false},"body":"","created_at":"2017-02-07T04:51:26Z","updated_at":"2017-02-07T04:54:51Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2600368e95552b9024523378ac5dcad386fc27f9","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593/commits","review_comments_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593/comments","review_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/comments{/number}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/issues/1593/comments","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/statuses/374210e0cccdba6c15d4f8d889efe2ec3927b586","head":{"label":"pongad:merge","ref":"merge","sha":"374210e0cccdba6c15d4f8d889efe2ec3927b586","user":{"login":"pongad","id":1617025,"avatar_url":"https://avatars.githubusercontent.com/u/1617025?v=3","gravatar_id":"","url":"https://api.github.com/users/pongad","html_url":"https://github.com/pongad","followers_url":"https://api.github.com/users/pongad/followers","following_url":"https://api.github.com/users/pongad/following{/other_user}","gists_url":"https://api.github.com/users/pongad/gists{/gist_id}","starred_url":"https://api.github.com/users/pongad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pongad/subscriptions","organizations_url":"https://api.github.com/users/pongad/orgs","repos_url":"https://api.github.com/users/pongad/repos","events_url":"https://api.github.com/users/pongad/events{/privacy}","received_events_url":"https://api.github.com/users/pongad/received_events","type":"User","site_admin":false},"repo":{"id":47151174,"name":"google-cloud-java","full_name":"pongad/google-cloud-java","owner":{"login":"pongad","id":1617025,"avatar_url":"https://avatars.githubusercontent.com/u/1617025?v=3","gravatar_id":"","url":"https://api.github.com/users/pongad","html_url":"https://github.com/pongad","followers_url":"https://api.github.com/users/pongad/followers","following_url":"https://api.github.com/users/pongad/following{/other_user}","gists_url":"https://api.github.com/users/pongad/gists{/gist_id}","starred_url":"https://api.github.com/users/pongad/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pongad/subscriptions","organizations_url":"https://api.github.com/users/pongad/orgs","repos_url":"https://api.github.com/users/pongad/repos","events_url":"https://api.github.com/users/pongad/events{/privacy}","received_events_url":"https://api.github.com/users/pongad/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pongad/google-cloud-java","description":"Google Cloud Client Library for Java","fork":true,"url":"https://api.github.com/repos/pongad/google-cloud-java","forks_url":"https://api.github.com/repos/pongad/google-cloud-java/forks","keys_url":"https://api.github.com/repos/pongad/google-cloud-java/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pongad/google-cloud-java/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pongad/google-cloud-java/teams","hooks_url":"https://api.github.com/repos/pongad/google-cloud-java/hooks","issue_events_url":"https://api.github.com/repos/pongad/google-cloud-java/issues/events{/number}","events_url":"https://api.github.com/repos/pongad/google-cloud-java/events","assignees_url":"https://api.github.com/repos/pongad/google-cloud-java/assignees{/user}","branches_url":"https://api.github.com/repos/pongad/google-cloud-java/branches{/branch}","tags_url":"https://api.github.com/repos/pongad/google-cloud-java/tags","blobs_url":"https://api.github.com/repos/pongad/google-cloud-java/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pongad/google-cloud-java/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pongad/google-cloud-java/git/refs{/sha}","trees_url":"https://api.github.com/repos/pongad/google-cloud-java/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pongad/google-cloud-java/statuses/{sha}","languages_url":"https://api.github.com/repos/pongad/google-cloud-java/languages","stargazers_url":"https://api.github.com/repos/pongad/google-cloud-java/stargazers","contributors_url":"https://api.github.com/repos/pongad/google-cloud-java/contributors","subscribers_url":"https://api.github.com/repos/pongad/google-cloud-java/subscribers","subscription_url":"https://api.github.com/repos/pongad/google-cloud-java/subscription","commits_url":"https://api.github.com/repos/pongad/google-cloud-java/commits{/sha}","git_commits_url":"https://api.github.com/repos/pongad/google-cloud-java/git/commits{/sha}","comments_url":"https://api.github.com/repos/pongad/google-cloud-java/comments{/number}","issue_comment_url":"https://api.github.com/repos/pongad/google-cloud-java/issues/comments{/number}","contents_url":"https://api.github.com/repos/pongad/google-cloud-java/contents/{+path}","compare_url":"https://api.github.com/repos/pongad/google-cloud-java/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pongad/google-cloud-java/merges","archive_url":"https://api.github.com/repos/pongad/google-cloud-java/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pongad/google-cloud-java/downloads","issues_url":"https://api.github.com/repos/pongad/google-cloud-java/issues{/number}","pulls_url":"https://api.github.com/repos/pongad/google-cloud-java/pulls{/number}","milestones_url":"https://api.github.com/repos/pongad/google-cloud-java/milestones{/number}","notifications_url":"https://api.github.com/repos/pongad/google-cloud-java/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pongad/google-cloud-java/labels{/name}","releases_url":"https://api.github.com/repos/pongad/google-cloud-java/releases{/id}","deployments_url":"https://api.github.com/repos/pongad/google-cloud-java/deployments","created_at":"2015-11-30T22:56:21Z","updated_at":"2016-12-04T23:35:55Z","pushed_at":"2017-02-07T04:50:18Z","git_url":"git://github.com/pongad/google-cloud-java.git","ssh_url":"git@github.com:pongad/google-cloud-java.git","clone_url":"https://github.com/pongad/google-cloud-java.git","svn_url":"https://github.com/pongad/google-cloud-java","homepage":"http://googlecloudplatform.github.io/gcloud-java/","size":85425,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"GoogleCloudPlatform:master","ref":"master","sha":"8f4828f01064900e93686b9ef6f69e02134ca7e7","user":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"repo":{"id":26181278,"name":"google-cloud-java","full_name":"GoogleCloudPlatform/google-cloud-java","owner":{"login":"GoogleCloudPlatform","id":2810941,"avatar_url":"https://avatars.githubusercontent.com/u/2810941?v=3","gravatar_id":"","url":"https://api.github.com/users/GoogleCloudPlatform","html_url":"https://github.com/GoogleCloudPlatform","followers_url":"https://api.github.com/users/GoogleCloudPlatform/followers","following_url":"https://api.github.com/users/GoogleCloudPlatform/following{/other_user}","gists_url":"https://api.github.com/users/GoogleCloudPlatform/gists{/gist_id}","starred_url":"https://api.github.com/users/GoogleCloudPlatform/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/GoogleCloudPlatform/subscriptions","organizations_url":"https://api.github.com/users/GoogleCloudPlatform/orgs","repos_url":"https://api.github.com/users/GoogleCloudPlatform/repos","events_url":"https://api.github.com/users/GoogleCloudPlatform/events{/privacy}","received_events_url":"https://api.github.com/users/GoogleCloudPlatform/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/GoogleCloudPlatform/google-cloud-java","description":"Google Cloud Client Library for Java","fork":false,"url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java","forks_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/forks","keys_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/keys{/key_id}","collaborators_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/teams","hooks_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/hooks","issue_events_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/issues/events{/number}","events_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/events","assignees_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/assignees{/user}","branches_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/branches{/branch}","tags_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/tags","blobs_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/git/refs{/sha}","trees_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/git/trees{/sha}","statuses_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/statuses/{sha}","languages_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/languages","stargazers_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/stargazers","contributors_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/contributors","subscribers_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/subscribers","subscription_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/subscription","commits_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/commits{/sha}","git_commits_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/git/commits{/sha}","comments_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/comments{/number}","issue_comment_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/issues/comments{/number}","contents_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/contents/{+path}","compare_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/compare/{base}...{head}","merges_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/merges","archive_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/downloads","issues_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/issues{/number}","pulls_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls{/number}","milestones_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/milestones{/number}","notifications_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/labels{/name}","releases_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/releases{/id}","deployments_url":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/deployments","created_at":"2014-11-04T17:57:16Z","updated_at":"2017-02-03T21:33:20Z","pushed_at":"2017-02-07T04:51:27Z","git_url":"git://github.com/GoogleCloudPlatform/google-cloud-java.git","ssh_url":"git@github.com:GoogleCloudPlatform/google-cloud-java.git","clone_url":"https://github.com/GoogleCloudPlatform/google-cloud-java.git","svn_url":"https://github.com/GoogleCloudPlatform/google-cloud-java","homepage":"http://googlecloudplatform.github.io/google-cloud-java/","size":90577,"stargazers_count":225,"watchers_count":225,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":129,"mirror_url":null,"open_issues_count":158,"forks":129,"open_issues":158,"watchers":225,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593"},"html":{"href":"https://github.com/GoogleCloudPlatform/google-cloud-java/pull/1593"},"issue":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/issues/1593"},"comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/issues/1593/comments"},"review_comments":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593/comments"},"review_comment":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/pulls/1593/commits"},"statuses":{"href":"https://api.github.com/repos/GoogleCloudPlatform/google-cloud-java/statuses/374210e0cccdba6c15d4f8d889efe2ec3927b586"}}}}
{"actor":{"display_login":"codacy-bot"}}