doc(samples): rewrite PendingStream Write API sample to match best practices#1603
doc(samples): rewrite PendingStream Write API sample to match best practices#1603stephaniewang526 merged 2 commits intogoogleapis:mainfrom
Conversation
| try (JsonStreamWriter writer = | ||
| JsonStreamWriter.newBuilder(parentTable.toString(), tableSchema).build()) { | ||
| try { | ||
| // Write two batches to the stream, each with 10 JSON records. A writer should be used for as |
There was a problem hiding this comment.
Can we add some explanation here when to use "batches"? My question reading this sample is why not just write 20 JSON records using 1 batch (why 2 batches)?
|
|
||
| public static WriteToDefaultStream create(String projectId, String datasetName, String tableName) | ||
| throws DescriptorValidationException, IOException, InterruptedException { | ||
| BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService(); |
There was a problem hiding this comment.
Can we add a comment here to explain why we are bringing in the BQ client and around schema conversion?
There was a problem hiding this comment.
Will do in followup; I changed this to just be PendingStream which encompasses the other cases, so we can finalize on a design in one place and replicate to the others.
|
|
||
| public class WriteToDefaultStream { | ||
|
|
||
| private final Phaser inflightRequestPhaser = new Phaser(1); |
There was a problem hiding this comment.
We don't prefer having anything out here like this, they should go inside either the driver method (runWriteToDefaultStream) or the body of the sample (writeToDefaultStream). Also, we need comment (explanation) around why we are using inflightRequestPhaser.
There was a problem hiding this comment.
Added a comment about the Phaser (which we need in order to wait for all responses before closing the stream)
Discussed the variables offline: the Write API is a special case where we need a stateful client and want to make explicit that users should keep the writer around for as long as possible.
| throws DescriptorValidationException, IOException, ExecutionException { | ||
| ApiFuture<AppendRowsResponse> future = this.streamWriter.append(jsonArr); | ||
| this.inflightRequestPhaser.register(); | ||
| ApiFutures.addCallback( |
There was a problem hiding this comment.
Can we add a comment here to explain this?
| import org.json.JSONArray; | ||
| import org.json.JSONObject; | ||
|
|
||
| public class WriteCommittedStream { |
There was a problem hiding this comment.
This name is a little confusing, maybe name it to WriteCommittedStreamSample? I am not sure the impact of changing the sample's name.
There was a problem hiding this comment.
I think most of our samples don't include "Sample" in the name. e.g., createTable.
Maybe WriteToCommittedStream?
There was a problem hiding this comment.
Make sense. Currently it sounded like a Stream. Will we just create a new file, switch the pointer and delete the old file?
There was a problem hiding this comment.
sgtm I'll do this in a followup
|
|
||
| public void cleanup() { | ||
| // Wait for all in-flight requests to complete. | ||
| this.inflightRequestPhaser.arriveAndAwaitAdvance(); |
There was a problem hiding this comment.
Close the JsonWriter here? Since you are doing a Finalize, with close, maybe we don't need to wait for inflight ourselves?
There was a problem hiding this comment.
Added the close, but as we discussed offline, we still need to wait for inflight requests to finish
|
|
||
| public static void writeCommittedStream(String projectId, String datasetName, String tableName) | ||
| throws DescriptorValidationException, InterruptedException, IOException { | ||
| // One time initialization. |
There was a problem hiding this comment.
Can we put the initialization code into a separate writer.initialize() method? I really like the structure of #1585 from a docs perspective.
There was a problem hiding this comment.
Changed it back. Not sure how to do it in a way that both exemplifies the structure and is "Good Java"
| if (response.hasError()) { | ||
| System.out.format("Error: %s\n", response.getError()); | ||
| } else { | ||
| System.out.format("Append %d success\n", response.getAppendResult().getOffset().getValue()); |
There was a problem hiding this comment.
For pending stream, show user a way to set stream_status_ and append to check on the status to fail the append?
There was a problem hiding this comment.
Done, thought I'm not great at Java, so maybe there's a better way?
|
|
||
| // Once all streams are done, commit all of them in one request. This example only has the one | ||
| // stream. | ||
| BatchCommitWriteStreamsRequest commitRequest = |
There was a problem hiding this comment.
We shouldn't commit for failed writes?
There was a problem hiding this comment.
Added an exception throw in cleanup and a comment about only committing successful streams.
|
|
||
| public void onSuccess(AppendRowsResponse response) { | ||
| if (response.hasError()) { | ||
| System.out.format("Error: %s\n", response.getError()); |
| } | ||
|
|
||
| public void onSuccess(AppendRowsResponse response) { | ||
| if (response.hasError()) { |
There was a problem hiding this comment.
I don't know what to do here...Maybe add a comment of how this can be retried? If we don't have a good retry case, should we have this sample?
There was a problem hiding this comment.
My $0.02: I think it's better to show how to check the AppendRowsResponse error status, rather than not show anything here.
There was a problem hiding this comment.
IIUC StreamWriter already handles this field which will invoke onFailure instead
I updated that code to show a little error handling; not sure if there's something more specific to show there
Start with just Pending stream which is the most complex to finalize design. Will update the other two in followup once consensus is reached.
|
Updated based on comments, and changed it to be only WritePendingStream for now since it encompasses the other cases. Once we finalize on a plan, I'll update the other 2 to match the same structure |
|
Merge-on-green attempted to merge your PR for 6 hours, but it was not mergeable because either one of your required status checks failed, one of your required reviews was not approved, or there is a do not merge label. Learn more about your required status checks here: https://help.github.com/en/github/administering-a-repository/enabling-required-status-checks. You can remove and reapply the label to re-run the bot. |
Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly:
Fixes #<issue_number_goes_here> ☕️
If you write sample code, please follow the samples format.