{"action":"created","comment":{"url":"https://api.github.com/repos/kmjung/beam/pulls/comments/226476291","pull_request_review_id":166308910,"id":226476291,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyNjQ3NjI5MQ==","diff_hunk":"@@ -17,161 +17,565 @@\n  */\n package org.apache.beam.sdk.io.gcp.bigquery;\n \n+import static com.google.common.base.Preconditions.checkArgument;\n import static com.google.common.base.Preconditions.checkNotNull;\n+import static com.google.common.base.Preconditions.checkState;\n \n-import com.google.cloud.bigquery.storage.v1alpha1.Storage;\n+import com.google.cloud.bigquery.storage.v1alpha1.Storage.ReadRowsRequest;\n+import com.google.cloud.bigquery.storage.v1alpha1.Storage.ReadRowsResponse;\n+import com.google.cloud.bigquery.storage.v1alpha1.Storage.ReadSession;\n+import com.google.cloud.bigquery.storage.v1alpha1.Storage.SplitReadStreamRequest;\n+import com.google.cloud.bigquery.storage.v1alpha1.Storage.SplitReadStreamResponse;\n+import com.google.cloud.bigquery.storage.v1alpha1.Storage.Stream;\n+import com.google.cloud.bigquery.storage.v1alpha1.Storage.StreamPosition;\n import com.google.cloud.bigquery.v3.RowOuterClass.Row;\n+import com.google.cloud.bigquery.v3.RowOuterClass.StructType;\n+import com.google.common.annotations.VisibleForTesting;\n import com.google.common.collect.ImmutableList;\n import java.io.IOException;\n import java.util.Iterator;\n import java.util.List;\n+import javax.annotation.concurrent.GuardedBy;\n import org.apache.beam.sdk.annotations.Experimental;\n+import org.apache.beam.sdk.annotations.Experimental.Kind;\n import org.apache.beam.sdk.coders.Coder;\n import org.apache.beam.sdk.io.BoundedSource;\n+import org.apache.beam.sdk.io.gcp.bigquery.BigQueryServices.ServerStream;\n+import org.apache.beam.sdk.io.gcp.bigquery.BigQueryServices.TableReadService;\n import org.apache.beam.sdk.options.PipelineOptions;\n import org.apache.beam.sdk.transforms.SerializableFunction;\n+import org.apache.beam.sdk.transforms.display.DisplayData;\n import org.slf4j.Logger;\n import org.slf4j.LoggerFactory;\n \n-/**\n- * A {@link BoundedSource} to read from existing read streams using the BigQuery parallel read API.\n- */\n-@Experimental(Experimental.Kind.SOURCE_SINK)\n+/** A source to read from a BigQuery storage read stream. */\n+@Experimental(Kind.SOURCE_SINK)\n public class BigQueryStorageStreamSource<T> extends BoundedSource<T> {\n \n-  private static final Logger LOG = LoggerFactory.getLogger(BigQueryStorageStreamSource.class);\n+  /** A value representing the split disposition of the source. */\n+  enum SplitDisposition {\n+    /** The current source represents the specified stream. */\n+    SELF,\n+\n+    /** The current source represents the primary child of the specified stream. */\n+    PRIMARY,\n+\n+    /** The current source represents the residual child of the specified stream. */\n+    RESIDUAL,\n+  }\n \n   static <T> BigQueryStorageStreamSource<T> create(\n-      BigQueryServices bqServices,\n+      ReadSession readSession,\n+      Stream stream,\n       SerializableFunction<SchemaAndRowProto, T> parseFn,\n-      Coder<T> coder,\n-      Storage.ReadSession readSession,\n-      Storage.StreamPosition streamPosition,\n-      Long readSizeBytes) {\n+      Coder<T> outputCoder,\n+      BigQueryServices bqServices) {\n     return new BigQueryStorageStreamSource<>(\n-        bqServices, parseFn, coder, readSession, streamPosition, readSizeBytes);\n+        readSession,\n+        stream,\n+        0,\n+        StreamOffsetRangeTracker.OFFSET_INFINITY,\n+        SplitDisposition.SELF,\n+        null,\n+        parseFn,\n+        outputCoder,\n+        bqServices);\n   }\n \n-  private final BigQueryServices bqServices;\n+  private final ReadSession readSession;\n+  private final Stream stream;\n+  private final long startOffset;\n+  private final long stopOffset;\n+  private final SplitDisposition splitDisposition;\n+  private final StreamPosition splitPosition;\n   private final SerializableFunction<SchemaAndRowProto, T> parseFn;\n-  private final Coder<T> coder;\n-  private final Storage.ReadSession readSession;\n-  private final Storage.StreamPosition streamPosition;\n-  private final Long readSizeBytes;\n+  private final Coder<T> outputCoder;\n+  private final BigQueryServices bqServices;\n \n-  BigQueryStorageStreamSource(\n-      BigQueryServices bqServices,\n+  private BigQueryStorageStreamSource(\n+      ReadSession readSession,\n+      Stream stream,\n+      long startOffset,\n+      long stopOffset,\n+      SplitDisposition splitDisposition,\n+      StreamPosition splitPosition,\n       SerializableFunction<SchemaAndRowProto, T> parseFn,\n-      Coder<T> coder,\n-      Storage.ReadSession readSession,\n-      Storage.StreamPosition streamPosition,\n-      Long readSizeBytes) {\n-    this.bqServices = checkNotNull(bqServices, \"bqServices\");\n-    this.parseFn = checkNotNull(parseFn, \"parseFn\");\n-    this.coder = checkNotNull(coder, \"coder\");\n+      Coder<T> outputCoder,\n+      BigQueryServices bqServices) {\n     this.readSession = checkNotNull(readSession, \"readSession\");\n-    this.streamPosition = checkNotNull(streamPosition, \"streamPosition\");\n-    this.readSizeBytes = readSizeBytes;\n+    this.stream = checkNotNull(stream, \"stream\");\n+    this.startOffset = startOffset;\n+    this.stopOffset = stopOffset;\n+    this.splitDisposition = checkNotNull(splitDisposition, \"splitDisposition\");\n+    this.splitPosition = splitPosition;\n+    this.parseFn = checkNotNull(parseFn, \"parseFn\");\n+    this.outputCoder = checkNotNull(outputCoder, \"outputCoder\");\n+    this.bqServices = checkNotNull(bqServices, \"bqServices\");\n+  }\n+\n+  @VisibleForTesting\n+  ReadSession getReadSession() {\n+    return readSession;\n+  }\n+\n+  @VisibleForTesting\n+  Stream getStream() {\n+    return stream;\n+  }\n+\n+  @VisibleForTesting\n+  long getStartOffset() {\n+    return startOffset;\n+  }\n+\n+  @VisibleForTesting\n+  long getStopOffset() {\n+    return stopOffset;\n+  }\n+\n+  @VisibleForTesting\n+  SplitDisposition getSplitDisposition() {\n+    return splitDisposition;\n+  }\n+\n+  @VisibleForTesting\n+  StreamPosition getSplitPosition() {\n+    return splitPosition;\n+  }\n+\n+  @Override\n+  public void validate() {\n+    checkState(startOffset >= 0, \"startOffset [%s] must be non-negative\", startOffset);\n+    checkState(stopOffset >= 0, \"stopOffset [%s] must be non-negative\", stopOffset);\n+    checkState(\n+        stopOffset >= startOffset,\n+        \"stopOffset [%s] cannot be less than startOffset [%s]\",\n+        stopOffset,\n+        startOffset);\n+    if (splitDisposition == SplitDisposition.SELF) {\n+      checkState(splitPosition == null, \"Split position cannot be specified with disposition SELF\");\n+    } else {\n+      checkState(\n+          splitPosition != null, \"Split position must be specified when disposition is not SELF\");\n+    }\n+  }\n+\n+  @Override\n+  public Coder<T> getOutputCoder() {\n+    return outputCoder;\n+  }\n+\n+  @Override\n+  public void populateDisplayData(DisplayData.Builder builder) {\n+    super.populateDisplayData(builder);\n+    builder.add(DisplayData.item(\"readSession\", readSession.getName()).withLabel(\"Read session\"));\n+    builder.add(DisplayData.item(\"stream\", stream.getName()).withLabel(\"Stream\"));\n   }\n \n   @Override\n-  public List<? extends BoundedSource<T>> split(\n-      long desiredBundleSizeBytes, PipelineOptions options) {\n-    // Stream source objects can't (currently) be split.\n+  public List<? extends BigQueryStorageStreamSource<T>> split(\n+      long desiredBundleSizeBytes, PipelineOptions options) throws Exception {\n     return ImmutableList.of(this);\n   }\n \n   @Override\n-  public long getEstimatedSizeBytes(PipelineOptions pipelineOptions) {\n-    return readSizeBytes != null ? readSizeBytes : 0;\n+  public long getEstimatedSizeBytes(PipelineOptions options) throws Exception {\n+    return 0L;","path":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryStorageStreamSource.java","position":200,"original_position":200,"commit_id":"1b7be999019ec9a4485cde8a10556c597493c065","original_commit_id":"1b7be999019ec9a4485cde8a10556c597493c065","user":{"login":"kmjung","id":10439787,"node_id":"MDQ6VXNlcjEwNDM5Nzg3","avatar_url":"https://avatars0.githubusercontent.com/u/10439787?v=4","gravatar_id":"","url":"https://api.github.com/users/kmjung","html_url":"https://github.com/kmjung","followers_url":"https://api.github.com/users/kmjung/followers","following_url":"https://api.github.com/users/kmjung/following{/other_user}","gists_url":"https://api.github.com/users/kmjung/gists{/gist_id}","starred_url":"https://api.github.com/users/kmjung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmjung/subscriptions","organizations_url":"https://api.github.com/users/kmjung/orgs","repos_url":"https://api.github.com/users/kmjung/repos","events_url":"https://api.github.com/users/kmjung/events{/privacy}","received_events_url":"https://api.github.com/users/kmjung/received_events","type":"User","site_admin":false},"body":"I don't think there is a good way to provide an estimate of the size of a stream since it can change significantly depending on how much data is read in the context of the underlying stream and in other streams in the read session. It can be anywhere from zero rows to the entire contents of the table.","created_at":"2018-10-18T21:45:49Z","updated_at":"2018-10-18T21:45:49Z","html_url":"https://github.com/kmjung/beam/pull/8#discussion_r226476291","pull_request_url":"https://api.github.com/repos/kmjung/beam/pulls/8","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/kmjung/beam/pulls/comments/226476291"},"html":{"href":"https://github.com/kmjung/beam/pull/8#discussion_r226476291"},"pull_request":{"href":"https://api.github.com/repos/kmjung/beam/pulls/8"}},"in_reply_to_id":226399873},"pull_request":{"url":"https://api.github.com/repos/kmjung/beam/pulls/8","id":219565724,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE5NTY1NzI0","html_url":"https://github.com/kmjung/beam/pull/8","diff_url":"https://github.com/kmjung/beam/pull/8.diff","patch_url":"https://github.com/kmjung/beam/pull/8.patch","issue_url":"https://api.github.com/repos/kmjung/beam/issues/8","number":8,"state":"open","locked":false,"title":"Support dynamic work rebalancing and progress estimation in the BQ stream source","user":{"login":"kmjung","id":10439787,"node_id":"MDQ6VXNlcjEwNDM5Nzg3","avatar_url":"https://avatars0.githubusercontent.com/u/10439787?v=4","gravatar_id":"","url":"https://api.github.com/users/kmjung","html_url":"https://github.com/kmjung","followers_url":"https://api.github.com/users/kmjung/followers","following_url":"https://api.github.com/users/kmjung/following{/other_user}","gists_url":"https://api.github.com/users/kmjung/gists{/gist_id}","starred_url":"https://api.github.com/users/kmjung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmjung/subscriptions","organizations_url":"https://api.github.com/users/kmjung/orgs","repos_url":"https://api.github.com/users/kmjung/repos","events_url":"https://api.github.com/users/kmjung/events{/privacy}","received_events_url":"https://api.github.com/users/kmjung/received_events","type":"User","site_admin":false},"body":"This pull request adds support for dynamic work rebalancing and progress estimation in the BigQuery storage stream source reader.It contains changes to:\r\n\r\n- Implement an offset range tracker for stream offsets which supports transitions to and from a \"pending split\" state for pending server-side split operations\r\n- Convert the test code for the BigQuery storage service to use an in-memory gRPC service and to consume (thinly wrapped versions of) GAX ServerStream types in the stream reader code\r\n- Support splitAtFraction and stream progress estimation directly in the stream reader.","created_at":"2018-10-02T02:05:21Z","updated_at":"2018-10-18T21:45:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4f86e7c2aad4a6f4aba4b7d8033501004a4734c2","assignee":null,"assignees":[],"requested_reviewers":[{"login":"gcasto","id":21225679,"node_id":"MDQ6VXNlcjIxMjI1Njc5","avatar_url":"https://avatars3.githubusercontent.com/u/21225679?v=4","gravatar_id":"","url":"https://api.github.com/users/gcasto","html_url":"https://github.com/gcasto","followers_url":"https://api.github.com/users/gcasto/followers","following_url":"https://api.github.com/users/gcasto/following{/other_user}","gists_url":"https://api.github.com/users/gcasto/gists{/gist_id}","starred_url":"https://api.github.com/users/gcasto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gcasto/subscriptions","organizations_url":"https://api.github.com/users/gcasto/orgs","repos_url":"https://api.github.com/users/gcasto/repos","events_url":"https://api.github.com/users/gcasto/events{/privacy}","received_events_url":"https://api.github.com/users/gcasto/received_events","type":"User","site_admin":false},{"login":"yirutang","id":30247570,"node_id":"MDQ6VXNlcjMwMjQ3NTcw","avatar_url":"https://avatars3.githubusercontent.com/u/30247570?v=4","gravatar_id":"","url":"https://api.github.com/users/yirutang","html_url":"https://github.com/yirutang","followers_url":"https://api.github.com/users/yirutang/followers","following_url":"https://api.github.com/users/yirutang/following{/other_user}","gists_url":"https://api.github.com/users/yirutang/gists{/gist_id}","starred_url":"https://api.github.com/users/yirutang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yirutang/subscriptions","organizations_url":"https://api.github.com/users/yirutang/orgs","repos_url":"https://api.github.com/users/yirutang/repos","events_url":"https://api.github.com/users/yirutang/events{/privacy}","received_events_url":"https://api.github.com/users/yirutang/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/kmjung/beam/pulls/8/commits","review_comments_url":"https://api.github.com/repos/kmjung/beam/pulls/8/comments","review_comment_url":"https://api.github.com/repos/kmjung/beam/pulls/comments{/number}","comments_url":"https://api.github.com/repos/kmjung/beam/issues/8/comments","statuses_url":"https://api.github.com/repos/kmjung/beam/statuses/1b7be999019ec9a4485cde8a10556c597493c065","head":{"label":"kmjung:bq_connector_release_split","ref":"bq_connector_release_split","sha":"1b7be999019ec9a4485cde8a10556c597493c065","user":{"login":"kmjung","id":10439787,"node_id":"MDQ6VXNlcjEwNDM5Nzg3","avatar_url":"https://avatars0.githubusercontent.com/u/10439787?v=4","gravatar_id":"","url":"https://api.github.com/users/kmjung","html_url":"https://github.com/kmjung","followers_url":"https://api.github.com/users/kmjung/followers","following_url":"https://api.github.com/users/kmjung/following{/other_user}","gists_url":"https://api.github.com/users/kmjung/gists{/gist_id}","starred_url":"https://api.github.com/users/kmjung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmjung/subscriptions","organizations_url":"https://api.github.com/users/kmjung/orgs","repos_url":"https://api.github.com/users/kmjung/repos","events_url":"https://api.github.com/users/kmjung/events{/privacy}","received_events_url":"https://api.github.com/users/kmjung/received_events","type":"User","site_admin":false},"repo":{"id":118979692,"node_id":"MDEwOlJlcG9zaXRvcnkxMTg5Nzk2OTI=","name":"beam","full_name":"kmjung/beam","private":false,"owner":{"login":"kmjung","id":10439787,"node_id":"MDQ6VXNlcjEwNDM5Nzg3","avatar_url":"https://avatars0.githubusercontent.com/u/10439787?v=4","gravatar_id":"","url":"https://api.github.com/users/kmjung","html_url":"https://github.com/kmjung","followers_url":"https://api.github.com/users/kmjung/followers","following_url":"https://api.github.com/users/kmjung/following{/other_user}","gists_url":"https://api.github.com/users/kmjung/gists{/gist_id}","starred_url":"https://api.github.com/users/kmjung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmjung/subscriptions","organizations_url":"https://api.github.com/users/kmjung/orgs","repos_url":"https://api.github.com/users/kmjung/repos","events_url":"https://api.github.com/users/kmjung/events{/privacy}","received_events_url":"https://api.github.com/users/kmjung/received_events","type":"User","site_admin":false},"html_url":"https://github.com/kmjung/beam","description":"Apache Beam","fork":true,"url":"https://api.github.com/repos/kmjung/beam","forks_url":"https://api.github.com/repos/kmjung/beam/forks","keys_url":"https://api.github.com/repos/kmjung/beam/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kmjung/beam/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kmjung/beam/teams","hooks_url":"https://api.github.com/repos/kmjung/beam/hooks","issue_events_url":"https://api.github.com/repos/kmjung/beam/issues/events{/number}","events_url":"https://api.github.com/repos/kmjung/beam/events","assignees_url":"https://api.github.com/repos/kmjung/beam/assignees{/user}","branches_url":"https://api.github.com/repos/kmjung/beam/branches{/branch}","tags_url":"https://api.github.com/repos/kmjung/beam/tags","blobs_url":"https://api.github.com/repos/kmjung/beam/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kmjung/beam/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kmjung/beam/git/refs{/sha}","trees_url":"https://api.github.com/repos/kmjung/beam/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kmjung/beam/statuses/{sha}","languages_url":"https://api.github.com/repos/kmjung/beam/languages","stargazers_url":"https://api.github.com/repos/kmjung/beam/stargazers","contributors_url":"https://api.github.com/repos/kmjung/beam/contributors","subscribers_url":"https://api.github.com/repos/kmjung/beam/subscribers","subscription_url":"https://api.github.com/repos/kmjung/beam/subscription","commits_url":"https://api.github.com/repos/kmjung/beam/commits{/sha}","git_commits_url":"https://api.github.com/repos/kmjung/beam/git/commits{/sha}","comments_url":"https://api.github.com/repos/kmjung/beam/comments{/number}","issue_comment_url":"https://api.github.com/repos/kmjung/beam/issues/comments{/number}","contents_url":"https://api.github.com/repos/kmjung/beam/contents/{+path}","compare_url":"https://api.github.com/repos/kmjung/beam/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kmjung/beam/merges","archive_url":"https://api.github.com/repos/kmjung/beam/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kmjung/beam/downloads","issues_url":"https://api.github.com/repos/kmjung/beam/issues{/number}","pulls_url":"https://api.github.com/repos/kmjung/beam/pulls{/number}","milestones_url":"https://api.github.com/repos/kmjung/beam/milestones{/number}","notifications_url":"https://api.github.com/repos/kmjung/beam/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kmjung/beam/labels{/name}","releases_url":"https://api.github.com/repos/kmjung/beam/releases{/id}","deployments_url":"https://api.github.com/repos/kmjung/beam/deployments","created_at":"2018-01-25T23:26:58Z","updated_at":"2018-05-17T16:05:52Z","pushed_at":"2018-10-12T19:01:38Z","git_url":"git://github.com/kmjung/beam.git","ssh_url":"git@github.com:kmjung/beam.git","clone_url":"https://github.com/kmjung/beam.git","svn_url":"https://github.com/kmjung/beam","homepage":"","size":99181,"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":3,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":3,"watchers":0,"default_branch":"master"}},"base":{"label":"kmjung:bq_connector_release_v2.7.0_rebase","ref":"bq_connector_release_v2.7.0_rebase","sha":"2552118940efee2033ac543eb942373cae5da66a","user":{"login":"kmjung","id":10439787,"node_id":"MDQ6VXNlcjEwNDM5Nzg3","avatar_url":"https://avatars0.githubusercontent.com/u/10439787?v=4","gravatar_id":"","url":"https://api.github.com/users/kmjung","html_url":"https://github.com/kmjung","followers_url":"https://api.github.com/users/kmjung/followers","following_url":"https://api.github.com/users/kmjung/following{/other_user}","gists_url":"https://api.github.com/users/kmjung/gists{/gist_id}","starred_url":"https://api.github.com/users/kmjung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmjung/subscriptions","organizations_url":"https://api.github.com/users/kmjung/orgs","repos_url":"https://api.github.com/users/kmjung/repos","events_url":"https://api.github.com/users/kmjung/events{/privacy}","received_events_url":"https://api.github.com/users/kmjung/received_events","type":"User","site_admin":false},"repo":{"id":118979692,"node_id":"MDEwOlJlcG9zaXRvcnkxMTg5Nzk2OTI=","name":"beam","full_name":"kmjung/beam","private":false,"owner":{"login":"kmjung","id":10439787,"node_id":"MDQ6VXNlcjEwNDM5Nzg3","avatar_url":"https://avatars0.githubusercontent.com/u/10439787?v=4","gravatar_id":"","url":"https://api.github.com/users/kmjung","html_url":"https://github.com/kmjung","followers_url":"https://api.github.com/users/kmjung/followers","following_url":"https://api.github.com/users/kmjung/following{/other_user}","gists_url":"https://api.github.com/users/kmjung/gists{/gist_id}","starred_url":"https://api.github.com/users/kmjung/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kmjung/subscriptions","organizations_url":"https://api.github.com/users/kmjung/orgs","repos_url":"https://api.github.com/users/kmjung/repos","events_url":"https://api.github.com/users/kmjung/events{/privacy}","received_events_url":"https://api.github.com/users/kmjung/received_events","type":"User","site_admin":false},"html_url":"https://github.com/kmjung/beam","description":"Apache Beam","fork":true,"url":"https://api.github.com/repos/kmjung/beam","forks_url":"https://api.github.com/repos/kmjung/beam/forks","keys_url":"https://api.github.com/repos/kmjung/beam/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kmjung/beam/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kmjung/beam/teams","hooks_url":"https://api.github.com/repos/kmjung/beam/hooks","issue_events_url":"https://api.github.com/repos/kmjung/beam/issues/events{/number}","events_url":"https://api.github.com/repos/kmjung/beam/events","assignees_url":"https://api.github.com/repos/kmjung/beam/assignees{/user}","branches_url":"https://api.github.com/repos/kmjung/beam/branches{/branch}","tags_url":"https://api.github.com/repos/kmjung/beam/tags","blobs_url":"https://api.github.com/repos/kmjung/beam/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kmjung/beam/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kmjung/beam/git/refs{/sha}","trees_url":"https://api.github.com/repos/kmjung/beam/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kmjung/beam/statuses/{sha}","languages_url":"https://api.github.com/repos/kmjung/beam/languages","stargazers_url":"https://api.github.com/repos/kmjung/beam/stargazers","contributors_url":"https://api.github.com/repos/kmjung/beam/contributors","subscribers_url":"https://api.github.com/repos/kmjung/beam/subscribers","subscription_url":"https://api.github.com/repos/kmjung/beam/subscription","commits_url":"https://api.github.com/repos/kmjung/beam/commits{/sha}","git_commits_url":"https://api.github.com/repos/kmjung/beam/git/commits{/sha}","comments_url":"https://api.github.com/repos/kmjung/beam/comments{/number}","issue_comment_url":"https://api.github.com/repos/kmjung/beam/issues/comments{/number}","contents_url":"https://api.github.com/repos/kmjung/beam/contents/{+path}","compare_url":"https://api.github.com/repos/kmjung/beam/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kmjung/beam/merges","archive_url":"https://api.github.com/repos/kmjung/beam/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kmjung/beam/downloads","issues_url":"https://api.github.com/repos/kmjung/beam/issues{/number}","pulls_url":"https://api.github.com/repos/kmjung/beam/pulls{/number}","milestones_url":"https://api.github.com/repos/kmjung/beam/milestones{/number}","notifications_url":"https://api.github.com/repos/kmjung/beam/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kmjung/beam/labels{/name}","releases_url":"https://api.github.com/repos/kmjung/beam/releases{/id}","deployments_url":"https://api.github.com/repos/kmjung/beam/deployments","created_at":"2018-01-25T23:26:58Z","updated_at":"2018-05-17T16:05:52Z","pushed_at":"2018-10-12T19:01:38Z","git_url":"git://github.com/kmjung/beam.git","ssh_url":"git@github.com:kmjung/beam.git","clone_url":"https://github.com/kmjung/beam.git","svn_url":"https://github.com/kmjung/beam","homepage":"","size":99181,"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":3,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":3,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/kmjung/beam/pulls/8"},"html":{"href":"https://github.com/kmjung/beam/pull/8"},"issue":{"href":"https://api.github.com/repos/kmjung/beam/issues/8"},"comments":{"href":"https://api.github.com/repos/kmjung/beam/issues/8/comments"},"review_comments":{"href":"https://api.github.com/repos/kmjung/beam/pulls/8/comments"},"review_comment":{"href":"https://api.github.com/repos/kmjung/beam/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/kmjung/beam/pulls/8/commits"},"statuses":{"href":"https://api.github.com/repos/kmjung/beam/statuses/1b7be999019ec9a4485cde8a10556c597493c065"}},"author_association":"OWNER"}}
{"actor":{"display_login":"kmjung"}}