{"action":"created","comment":{"url":"https://api.github.com/repos/apache/samza/pulls/comments/184775418","pull_request_review_id":116036015,"id":184775418,"diff_hunk":"@@ -18,205 +18,221 @@\n  */\n package org.apache.samza.zk;\n \n-import junit.framework.Assert;\n+import com.google.common.collect.ImmutableList;\n import org.I0Itec.zkclient.ZkClient;\n+import org.apache.commons.lang3.RandomStringUtils;\n import org.apache.samza.config.ZkConfig;\n import org.apache.samza.testUtils.EmbeddedZookeeper;\n import org.apache.samza.util.NoOpMetricsRegistry;\n \n-import java.util.ArrayList;\n import java.util.List;\n import java.util.concurrent.CountDownLatch;\n import java.util.concurrent.TimeUnit;\n import java.util.concurrent.atomic.AtomicInteger;\n-//import org.junit.After;\n-//import org.junit.AfterClass;\n-//import org.junit.Before;\n-//import org.junit.BeforeClass;\n-//import org.junit.Test;\n+import org.apache.samza.zk.ZkBarrierForVersionUpgrade.State;\n+import org.junit.After;\n+import org.junit.AfterClass;\n+import org.junit.Before;\n+import org.junit.BeforeClass;\n+import org.junit.Test;\n+\n+import static junit.framework.Assert.*;\n+\n \n // TODO: Rename this such that it is clear that it is an integration test and NOT unit test\n public class TestZkBarrierForVersionUpgrade {\n+  private static final String BARRIER_VERSION = \"1\";\n   private static EmbeddedZookeeper zkServer = null;\n   private static String testZkConnectionString = null;\n   private ZkUtils zkUtils;\n   private ZkUtils zkUtils1;\n \n-  //@BeforeClass\n+  @BeforeClass\n   public static void test() {\n     zkServer = new EmbeddedZookeeper();\n     zkServer.setup();\n-    testZkConnectionString = \"127.0.0.1:\" + zkServer.getPort();\n+    testZkConnectionString = String.format(\"127.0.0.1:%d\", zkServer.getPort());\n   }\n \n-  //@Before\n+  @Before\n   public void testSetup() {\n     ZkClient zkClient = new ZkClient(testZkConnectionString, ZkConfig.DEFAULT_SESSION_TIMEOUT_MS, ZkConfig.DEFAULT_CONNECTION_TIMEOUT_MS);\n     this.zkUtils = new ZkUtils(new ZkKeyBuilder(\"group1\"), zkClient, ZkConfig.DEFAULT_CONNECTION_TIMEOUT_MS, new NoOpMetricsRegistry());\n     ZkClient zkClient1 = new ZkClient(testZkConnectionString, ZkConfig.DEFAULT_SESSION_TIMEOUT_MS, ZkConfig.DEFAULT_CONNECTION_TIMEOUT_MS);\n     this.zkUtils1 = new ZkUtils(new ZkKeyBuilder(\"group1\"), zkClient1, ZkConfig.DEFAULT_CONNECTION_TIMEOUT_MS, new NoOpMetricsRegistry());\n   }\n \n-  //@After\n+  @After\n   public void testTearDown() {\n     zkUtils.close();\n     zkUtils1.close();\n   }\n \n-  //@AfterClass\n+  @AfterClass\n   public static void teardown() {\n     zkServer.teardown();\n   }\n \n-  //@Test\n-  public void testZkBarrierForVersionUpgrade() {\n-    String barrierId = zkUtils.getKeyBuilder().getRootPath() + \"/b1\";\n-    String ver = \"1\";\n-    List<String> processors = new ArrayList<>();\n-    processors.add(\"p1\");\n-    processors.add(\"p2\");\n-    final CountDownLatch latch = new CountDownLatch(2);\n-    final AtomicInteger stateChangedCalled = new AtomicInteger(0);\n-\n-    ZkBarrierForVersionUpgrade processor1Barrier = new ZkBarrierForVersionUpgrade(barrierId, zkUtils, new ZkBarrierListener() {\n-      @Override\n-      public void onBarrierCreated(String version) {\n-      }\n+  static class TestZkBarrierListener implements ZkBarrierListener {\n \n-      @Override\n-      public void onBarrierStateChanged(String version, ZkBarrierForVersionUpgrade.State state) {\n-        if (state.equals(ZkBarrierForVersionUpgrade.State.DONE)) {\n-          latch.countDown();\n-          stateChangedCalled.incrementAndGet();\n-        }\n-      }\n+    private final CountDownLatch stateChangedLatch;\n+    private final AtomicInteger stateChangedCounter;\n+    private final State expectedState;\n+\n+    TestZkBarrierListener(CountDownLatch stateChangedLatch, AtomicInteger stateChangedCounter, State expectedState) {\n+      this.stateChangedLatch = stateChangedLatch;\n+      this.stateChangedCounter = stateChangedCounter;\n+      this.expectedState = expectedState;\n+    }\n \n-      @Override\n-      public void onBarrierError(String version, Throwable t) {\n+    @Override\n+    public void onBarrierCreated(String version) {}\n \n+    @Override\n+    public void onBarrierStateChanged(String version, State state) {\n+      if (state.equals(expectedState)) {\n+        stateChangedCounter.incrementAndGet();\n+        stateChangedLatch.countDown();\n       }\n-    });\n+    }\n \n-    processor1Barrier.create(ver, processors);\n-    processor1Barrier.join(ver, \"p1\");\n+    @Override\n+    public void onBarrierError(String version, Throwable t) {}\n+  }\n \n-    ZkBarrierForVersionUpgrade processor2Barrier = new ZkBarrierForVersionUpgrade(barrierId, zkUtils1, new ZkBarrierListener() {\n-      @Override\n-      public void onBarrierCreated(String version) {\n-      }\n+  @Test\n+  public void testZkBarrierForVersionUpgrade() {\n+    String barrierId = String.format(\"%s/%s\", zkUtils1.getKeyBuilder().getRootPath(), RandomStringUtils.randomAlphabetic(4));\n \n-      @Override\n-      public void onBarrierStateChanged(String version, ZkBarrierForVersionUpgrade.State state) {\n-        if (state.equals(ZkBarrierForVersionUpgrade.State.DONE)) {\n-          latch.countDown();\n-          stateChangedCalled.incrementAndGet();\n-        }\n-      }\n+    List<String> processors = ImmutableList.of(\"p1\", \"p2\");\n \n-      @Override\n-      public void onBarrierError(String version, Throwable t) {\n+    CountDownLatch latch = new CountDownLatch(2);\n+    AtomicInteger stateChangedCalled = new AtomicInteger(0);\n+    TestZkBarrierListener listener = new TestZkBarrierListener(latch, stateChangedCalled, State.DONE);\n \n-      }\n-    });\n-    processor2Barrier.join(ver, \"p2\");\n+    ZkBarrierForVersionUpgrade processor1Barrier = new ZkBarrierForVersionUpgrade(barrierId, zkUtils, listener);\n+    ZkBarrierForVersionUpgrade processor2Barrier = new ZkBarrierForVersionUpgrade(barrierId, zkUtils1, listener);\n+\n+    processor1Barrier.create(BARRIER_VERSION, processors);\n+\n+    State barrierState = zkUtils.getZkClient().readData(barrierId + \"/barrier_1/barrier_state\");\n+    assertEquals(State.NEW, barrierState);\n+\n+    processor1Barrier.join(BARRIER_VERSION, \"p1\");\n+    processor2Barrier.join(BARRIER_VERSION, \"p2\");\n \n     boolean result = false;\n     try {\n       result = latch.await(10000, TimeUnit.MILLISECONDS);\n     } catch (InterruptedException e) {\n       e.printStackTrace();\n     }\n-    Assert.assertTrue(\"Barrier failed to complete within test timeout.\", result);\n+    assertTrue(\"Barrier failed to complete within test timeout.\", result);\n+\n+    List<String> children = zkUtils.getZkClient().getChildren(barrierId + \"/barrier_1/barrier_participants\");\n+    barrierState = zkUtils.getZkClient().readData(barrierId + \"/barrier_1/barrier_state\");\n+    assertEquals(State.DONE, barrierState);\n+    assertNotNull(children);\n+    assertEquals(\"Unexpected barrier state. Didn't find two processors.\", 2, children.size());\n+    assertEquals(\"Unexpected barrier state. Didn't find the expected members.\", processors, children);\n+    assertEquals(2, stateChangedCalled.get());\n+  }\n+\n+  @Test\n+  public void testZkBarrierForVersionUpgradeWithTimeOut() {\n+    String barrierId = String.format(\"%s/%s\", zkUtils1.getKeyBuilder().getRootPath(), RandomStringUtils.randomAlphabetic(4));\n+    List<String> processors = ImmutableList.of(\"p1\", \"p2\", \"p3\");\n+\n+    AtomicInteger timeoutStateChangeCalled = new AtomicInteger(0);\n+    CountDownLatch latch = new CountDownLatch(2);\n+    TestZkBarrierListener listener = new TestZkBarrierListener(latch, timeoutStateChangeCalled, State.TIMED_OUT);\n+\n+    ZkBarrierForVersionUpgrade processor1Barrier = new ZkBarrierForVersionUpgrade(barrierId, zkUtils, listener);\n+    ZkBarrierForVersionUpgrade processor2Barrier = new ZkBarrierForVersionUpgrade(barrierId, zkUtils1, listener);\n \n+    processor1Barrier.create(BARRIER_VERSION, processors);\n+\n+    processor1Barrier.join(BARRIER_VERSION, \"p1\");\n+    processor2Barrier.join(BARRIER_VERSION, \"p2\");\n+\n+    processor1Barrier.expire(BARRIER_VERSION);\n+    boolean result = false;\n     try {\n-      List<String> children = zkUtils.getZkClient().getChildren(barrierId + \"/barrier_v1/barrier_participants\");\n-      Assert.assertNotNull(children);\n-      Assert.assertEquals(\"Unexpected barrier state. Didn't find two processors.\", 2, children.size());\n-      Assert.assertEquals(\"Unexpected barrier state. Didn't find the expected members.\", processors, children);\n-    } catch (Exception e) {\n-      // no-op\n+      result = latch.await(10000, TimeUnit.MILLISECONDS);\n+    } catch (InterruptedException e) {\n+      e.printStackTrace();\n     }\n-    Assert.assertEquals(2, stateChangedCalled.get());\n+    assertTrue(\"Barrier Timeout test failed to complete within test timeout.\", result);\n+\n+    List<String> children = zkUtils.getZkClient().getChildren(barrierId + \"/barrier_1/barrier_participants\");\n+    State barrierState = zkUtils.getZkClient().readData(barrierId + \"/barrier_1/barrier_state\");\n+    assertEquals(State.TIMED_OUT, barrierState);\n+    assertNotNull(children);\n+    assertEquals(\"Unexpected barrier state. Didn't find two processors.\", 2, children.size());\n+    assertEquals(\"Unexpected barrier state. Didn't find the expected members.\", ImmutableList.of(\"p1\", \"p2\"), children);\n+    assertEquals(2, timeoutStateChangeCalled.get());","path":"samza-core/src/test/java/org/apache/samza/zk/TestZkBarrierForVersionUpgrade.java","position":218,"original_position":218,"commit_id":"856c29d14d579c36e7d41dc7d574d4ea2752fd8f","original_commit_id":"856c29d14d579c36e7d41dc7d574d4ea2752fd8f","user":{"login":"vjagadish","id":7350060,"avatar_url":"https://avatars1.githubusercontent.com/u/7350060?v=4","gravatar_id":"","url":"https://api.github.com/users/vjagadish","html_url":"https://github.com/vjagadish","followers_url":"https://api.github.com/users/vjagadish/followers","following_url":"https://api.github.com/users/vjagadish/following{/other_user}","gists_url":"https://api.github.com/users/vjagadish/gists{/gist_id}","starred_url":"https://api.github.com/users/vjagadish/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vjagadish/subscriptions","organizations_url":"https://api.github.com/users/vjagadish/orgs","repos_url":"https://api.github.com/users/vjagadish/repos","events_url":"https://api.github.com/users/vjagadish/events{/privacy}","received_events_url":"https://api.github.com/users/vjagadish/received_events","type":"User","site_admin":false},"body":"Could this be flaky in this scenario?\r\n\r\n- thread-1\r\nawait on the latch\r\ncheck counter==2\r\n\r\n- zk-client thread\r\nlistener.onEvent() is called for processor-1\r\nprocessor1 increments counter\r\nprocessor1 counts down the latch\r\nlistener.onEvent() is called for processor-2\r\nprocessor2 increments the counter\r\n\r\nCould the counter-check in thread-1 succeed/fail depending on whether the ZkClient thread got to deliver the event for processor2?\r\n\r\nWould be simpler to use a single latch with count = 2 or use separate listener instances","created_at":"2018-04-27T18:45:45Z","updated_at":"2018-04-27T18:49:39Z","html_url":"https://github.com/apache/samza/pull/490#discussion_r184775418","pull_request_url":"https://api.github.com/repos/apache/samza/pulls/490","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/apache/samza/pulls/comments/184775418"},"html":{"href":"https://github.com/apache/samza/pull/490#discussion_r184775418"},"pull_request":{"href":"https://api.github.com/repos/apache/samza/pulls/490"}}},"pull_request":{"url":"https://api.github.com/repos/apache/samza/pulls/490","id":184552831,"html_url":"https://github.com/apache/samza/pull/490","diff_url":"https://github.com/apache/samza/pull/490.diff","patch_url":"https://github.com/apache/samza/pull/490.patch","issue_url":"https://api.github.com/repos/apache/samza/issues/490","number":490,"state":"open","locked":false,"title":"SAMZA-1689: Add validations before state transitions in ZkBarrierForVersionUpgrade.","user":{"login":"shanthoosh","id":483745,"avatar_url":"https://avatars2.githubusercontent.com/u/483745?v=4","gravatar_id":"","url":"https://api.github.com/users/shanthoosh","html_url":"https://github.com/shanthoosh","followers_url":"https://api.github.com/users/shanthoosh/followers","following_url":"https://api.github.com/users/shanthoosh/following{/other_user}","gists_url":"https://api.github.com/users/shanthoosh/gists{/gist_id}","starred_url":"https://api.github.com/users/shanthoosh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shanthoosh/subscriptions","organizations_url":"https://api.github.com/users/shanthoosh/orgs","repos_url":"https://api.github.com/users/shanthoosh/repos","events_url":"https://api.github.com/users/shanthoosh/events{/privacy}","received_events_url":"https://api.github.com/users/shanthoosh/received_events","type":"User","site_admin":false},"body":"Prevent invalid state updations on barrier.\r\n* Introduced a additional barrier state NEW.\r\n* Add state validations before updating the barrier.\r\n* Fix existing TestZkBarrier tests that are disabled and add new tests\r\n  to verify the intended behavior.\r\n\r\n","created_at":"2018-04-27T08:13:00Z","updated_at":"2018-04-27T18:49:39Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2446aea939b19bb713f97aff9e08b04915f3ca47","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/apache/samza/pulls/490/commits","review_comments_url":"https://api.github.com/repos/apache/samza/pulls/490/comments","review_comment_url":"https://api.github.com/repos/apache/samza/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apache/samza/issues/490/comments","statuses_url":"https://api.github.com/repos/apache/samza/statuses/856c29d14d579c36e7d41dc7d574d4ea2752fd8f","head":{"label":"shanthoosh:fix_barrier_state_transitions","ref":"fix_barrier_state_transitions","sha":"856c29d14d579c36e7d41dc7d574d4ea2752fd8f","user":{"login":"shanthoosh","id":483745,"avatar_url":"https://avatars2.githubusercontent.com/u/483745?v=4","gravatar_id":"","url":"https://api.github.com/users/shanthoosh","html_url":"https://github.com/shanthoosh","followers_url":"https://api.github.com/users/shanthoosh/followers","following_url":"https://api.github.com/users/shanthoosh/following{/other_user}","gists_url":"https://api.github.com/users/shanthoosh/gists{/gist_id}","starred_url":"https://api.github.com/users/shanthoosh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shanthoosh/subscriptions","organizations_url":"https://api.github.com/users/shanthoosh/orgs","repos_url":"https://api.github.com/users/shanthoosh/repos","events_url":"https://api.github.com/users/shanthoosh/events{/privacy}","received_events_url":"https://api.github.com/users/shanthoosh/received_events","type":"User","site_admin":false},"repo":{"id":69699342,"name":"samza","full_name":"shanthoosh/samza","owner":{"login":"shanthoosh","id":483745,"avatar_url":"https://avatars2.githubusercontent.com/u/483745?v=4","gravatar_id":"","url":"https://api.github.com/users/shanthoosh","html_url":"https://github.com/shanthoosh","followers_url":"https://api.github.com/users/shanthoosh/followers","following_url":"https://api.github.com/users/shanthoosh/following{/other_user}","gists_url":"https://api.github.com/users/shanthoosh/gists{/gist_id}","starred_url":"https://api.github.com/users/shanthoosh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/shanthoosh/subscriptions","organizations_url":"https://api.github.com/users/shanthoosh/orgs","repos_url":"https://api.github.com/users/shanthoosh/repos","events_url":"https://api.github.com/users/shanthoosh/events{/privacy}","received_events_url":"https://api.github.com/users/shanthoosh/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/shanthoosh/samza","description":"Mirror of Apache Samza","fork":true,"url":"https://api.github.com/repos/shanthoosh/samza","forks_url":"https://api.github.com/repos/shanthoosh/samza/forks","keys_url":"https://api.github.com/repos/shanthoosh/samza/keys{/key_id}","collaborators_url":"https://api.github.com/repos/shanthoosh/samza/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/shanthoosh/samza/teams","hooks_url":"https://api.github.com/repos/shanthoosh/samza/hooks","issue_events_url":"https://api.github.com/repos/shanthoosh/samza/issues/events{/number}","events_url":"https://api.github.com/repos/shanthoosh/samza/events","assignees_url":"https://api.github.com/repos/shanthoosh/samza/assignees{/user}","branches_url":"https://api.github.com/repos/shanthoosh/samza/branches{/branch}","tags_url":"https://api.github.com/repos/shanthoosh/samza/tags","blobs_url":"https://api.github.com/repos/shanthoosh/samza/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/shanthoosh/samza/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/shanthoosh/samza/git/refs{/sha}","trees_url":"https://api.github.com/repos/shanthoosh/samza/git/trees{/sha}","statuses_url":"https://api.github.com/repos/shanthoosh/samza/statuses/{sha}","languages_url":"https://api.github.com/repos/shanthoosh/samza/languages","stargazers_url":"https://api.github.com/repos/shanthoosh/samza/stargazers","contributors_url":"https://api.github.com/repos/shanthoosh/samza/contributors","subscribers_url":"https://api.github.com/repos/shanthoosh/samza/subscribers","subscription_url":"https://api.github.com/repos/shanthoosh/samza/subscription","commits_url":"https://api.github.com/repos/shanthoosh/samza/commits{/sha}","git_commits_url":"https://api.github.com/repos/shanthoosh/samza/git/commits{/sha}","comments_url":"https://api.github.com/repos/shanthoosh/samza/comments{/number}","issue_comment_url":"https://api.github.com/repos/shanthoosh/samza/issues/comments{/number}","contents_url":"https://api.github.com/repos/shanthoosh/samza/contents/{+path}","compare_url":"https://api.github.com/repos/shanthoosh/samza/compare/{base}...{head}","merges_url":"https://api.github.com/repos/shanthoosh/samza/merges","archive_url":"https://api.github.com/repos/shanthoosh/samza/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/shanthoosh/samza/downloads","issues_url":"https://api.github.com/repos/shanthoosh/samza/issues{/number}","pulls_url":"https://api.github.com/repos/shanthoosh/samza/pulls{/number}","milestones_url":"https://api.github.com/repos/shanthoosh/samza/milestones{/number}","notifications_url":"https://api.github.com/repos/shanthoosh/samza/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/shanthoosh/samza/labels{/name}","releases_url":"https://api.github.com/repos/shanthoosh/samza/releases{/id}","deployments_url":"https://api.github.com/repos/shanthoosh/samza/deployments","created_at":"2016-09-30T20:20:29Z","updated_at":"2018-04-27T01:39:23Z","pushed_at":"2018-04-27T08:10:36Z","git_url":"git://github.com/shanthoosh/samza.git","ssh_url":"git@github.com:shanthoosh/samza.git","clone_url":"https://github.com/shanthoosh/samza.git","svn_url":"https://github.com/shanthoosh/samza","homepage":null,"size":20155,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apache:master","ref":"master","sha":"af06c8d0c77acf833af1d1ac538763c411b107ef","user":{"login":"apache","id":47359,"avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"repo":{"id":32199982,"name":"samza","full_name":"apache/samza","owner":{"login":"apache","id":47359,"avatar_url":"https://avatars0.githubusercontent.com/u/47359?v=4","gravatar_id":"","url":"https://api.github.com/users/apache","html_url":"https://github.com/apache","followers_url":"https://api.github.com/users/apache/followers","following_url":"https://api.github.com/users/apache/following{/other_user}","gists_url":"https://api.github.com/users/apache/gists{/gist_id}","starred_url":"https://api.github.com/users/apache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apache/subscriptions","organizations_url":"https://api.github.com/users/apache/orgs","repos_url":"https://api.github.com/users/apache/repos","events_url":"https://api.github.com/users/apache/events{/privacy}","received_events_url":"https://api.github.com/users/apache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apache/samza","description":"Mirror of Apache Samza","fork":false,"url":"https://api.github.com/repos/apache/samza","forks_url":"https://api.github.com/repos/apache/samza/forks","keys_url":"https://api.github.com/repos/apache/samza/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apache/samza/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apache/samza/teams","hooks_url":"https://api.github.com/repos/apache/samza/hooks","issue_events_url":"https://api.github.com/repos/apache/samza/issues/events{/number}","events_url":"https://api.github.com/repos/apache/samza/events","assignees_url":"https://api.github.com/repos/apache/samza/assignees{/user}","branches_url":"https://api.github.com/repos/apache/samza/branches{/branch}","tags_url":"https://api.github.com/repos/apache/samza/tags","blobs_url":"https://api.github.com/repos/apache/samza/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apache/samza/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apache/samza/git/refs{/sha}","trees_url":"https://api.github.com/repos/apache/samza/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apache/samza/statuses/{sha}","languages_url":"https://api.github.com/repos/apache/samza/languages","stargazers_url":"https://api.github.com/repos/apache/samza/stargazers","contributors_url":"https://api.github.com/repos/apache/samza/contributors","subscribers_url":"https://api.github.com/repos/apache/samza/subscribers","subscription_url":"https://api.github.com/repos/apache/samza/subscription","commits_url":"https://api.github.com/repos/apache/samza/commits{/sha}","git_commits_url":"https://api.github.com/repos/apache/samza/git/commits{/sha}","comments_url":"https://api.github.com/repos/apache/samza/comments{/number}","issue_comment_url":"https://api.github.com/repos/apache/samza/issues/comments{/number}","contents_url":"https://api.github.com/repos/apache/samza/contents/{+path}","compare_url":"https://api.github.com/repos/apache/samza/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apache/samza/merges","archive_url":"https://api.github.com/repos/apache/samza/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apache/samza/downloads","issues_url":"https://api.github.com/repos/apache/samza/issues{/number}","pulls_url":"https://api.github.com/repos/apache/samza/pulls{/number}","milestones_url":"https://api.github.com/repos/apache/samza/milestones{/number}","notifications_url":"https://api.github.com/repos/apache/samza/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apache/samza/labels{/name}","releases_url":"https://api.github.com/repos/apache/samza/releases{/id}","deployments_url":"https://api.github.com/repos/apache/samza/deployments","created_at":"2015-03-14T07:00:05Z","updated_at":"2018-04-27T17:23:21Z","pushed_at":"2018-04-27T17:23:15Z","git_url":"git://github.com/apache/samza.git","ssh_url":"git@github.com:apache/samza.git","clone_url":"https://github.com/apache/samza.git","svn_url":"https://github.com/apache/samza","homepage":null,"size":19592,"stargazers_count":419,"watchers_count":419,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":185,"mirror_url":null,"archived":false,"open_issues_count":18,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":185,"open_issues":18,"watchers":419,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apache/samza/pulls/490"},"html":{"href":"https://github.com/apache/samza/pull/490"},"issue":{"href":"https://api.github.com/repos/apache/samza/issues/490"},"comments":{"href":"https://api.github.com/repos/apache/samza/issues/490/comments"},"review_comments":{"href":"https://api.github.com/repos/apache/samza/pulls/490/comments"},"review_comment":{"href":"https://api.github.com/repos/apache/samza/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apache/samza/pulls/490/commits"},"statuses":{"href":"https://api.github.com/repos/apache/samza/statuses/856c29d14d579c36e7d41dc7d574d4ea2752fd8f"}},"author_association":"NONE"}}
{"actor":{"display_login":"vjagadish"}}