googleapis / java-bigquerystorage

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getting StreamWriterClosedException in BQ Storage Write Api

SubhamSinghal opened this issue · comments

I have been using java service which write records to BQ using storage api. Its been running fine for almost a week and then suddenly i see below StreamWriterClosedException in application log.

at bq.DataWriter.append(DataWriter.java:61)
	at bq.DataWriter$AppendCompleteCallback.onFailure(DataWriter.java:109)
	at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:67)
	at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1132)
	at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:31)
	at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1270)
	at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:1038)
	at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:808)
	at com.google.api.core.AbstractApiFuture$InternalSettableFuture.setException(AbstractApiFuture.java:94)
	at com.google.api.core.AbstractApiFuture.setException(AbstractApiFuture.java:76)
	at com.google.api.core.SettableApiFuture.setException(SettableApiFuture.java:51)
	at com.google.cloud.bigquery.storage.v1.StreamWriter.cleanupInflightRequests(StreamWriter.java:585)
	at com.google.cloud.bigquery.storage.v1.StreamWriter.appendLoop(StreamWriter.java:496)
	at com.google.cloud.bigquery.storage.v1.StreamWriter.access$1000(StreamWriter.java:51)
	at com.google.cloud.bigquery.storage.v1.StreamWriter$1.run(StreamWriter.java:221)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: com.google.cloud.bigquery.storage.v1.Exceptions$StreamWriterClosedException: FAILED_PRECONDITION: Connection is closed due to com.google.api.gax.rpc.InternalException: io.grpc.StatusRuntimeException: INTERNAL: An error occurred while verifying authorization. Entity: projects/project_id/datasets/dataset_name/tables/table_name/ Entity: projects/project_id/datasets/dataset_name/tables/table_name/_default
	at com.google.cloud.bigquery.storage.v1.StreamWriter.appendInternal(StreamWriter.java:327)
	at com.google.cloud.bigquery.storage.v1.StreamWriter.append(StreamWriter.java:287)
	at com.google.cloud.bigquery.storage.v1.JsonStreamWriter.append(JsonStreamWriter.java:166)
	at com.google.cloud.bigquery.storage.v1.JsonStreamWriter.append(JsonStreamWriter.java:109)

This is my build.gradle dependency for storage write api

implementation platform('com.google.cloud:libraries-bom:26.1.0')
implementation 'com.google.cloud:google-cloud-bigquerystorage'
implementation 'com.google.cloud:google-cloud-bigquery'

I am using spring boot version 2.7.2

here is issue link raised in bq forum as well: https://www.googlecloudcommunity.com/gc/Data-Analytics/Getting-StreamWriterClosedException-in-BQ-Storage-Write-Api/m-p/476293#M766

Hi @SubhamSinghal,
We need more information to debug the issue. Can you provide a code snippet and details on what changed in the project setup: change in permissions, what resource is encountering the issue etc, authentication method ?

Hi @Neenu1995
We are using gcp service account for authentication. There is no change in permission as i have observed that issue got resolved after restart.

Here is code snippet for BQ default storage api client:
BQClient.java

public void loadData(JSONArray jsonArray, String tableName)
            throws DescriptorValidationException, InterruptedException, IOException {

        TableName parentTable = TableName.of(projectId, bqDataSetName, tableName);
        DataWriter writer = bqStreamRepository.getDataWriter(parentTable);

        writer.append(new AppendContext(jsonArray, 0));
        int size = jsonArray.length();
        log.info("Appended {} records successfully.", size);
    }

DataWriter code is same as mentioned here storage api java client

We are managing DataWriter objects in a hashMap, this to have a single DataWriter instance per table for project lifecycle.
Code:

BqStreamRepository.java

  private Map<String, DataWriter> dataWriterMap = new ConcurrentHashMap<>();

     public DataWriter getDataWriter(TableName tableName) throws Descriptors.DescriptorValidationException, IOException, InterruptedException {
         DataWriter dataWriter = dataWriterMap.getOrDefault(tableName.getTable(), null);
         if(dataWriter == null) {
             synchronized (this) {
                 if(dataWriter == null) {
                     dataWriter = new DataWriter();
                     // One time initialization for the worker.
                     dataWriter.initialize(tableName);
                     dataWriterMap.put(tableName.getTable(), dataWriter);
                 }
             }
         }
         return dataWriter;
     }

     @PreDestroy
    public void cleanUp() {
         // Final cleanup for the stream during worker teardown.
         log.info("Cleaning up data writer");
         dataWriterMap.forEach((tableName, dataWriter) -> dataWriter.cleanup());
     }

I have recently updated com.google.cloud:libraries-bom version to 26.1.3. I am facing one more issue related to connection close exception:

java.lang.RuntimeException: com.google.cloud.bigquery.storage.v1.Exceptions$StreamWriterClosedException: FAILED_PRECONDITION: Connection is closed due to com.google.api.gax.rpc.InternalException: io.grpc.StatusRuntimeException: INTERNAL: Internal error encountered. Entity: projects/project_name/datasets/dataset_name/tables/table_name/_default
at bq.DataWriter.append(DataWriter.java:61)
at bq.DataWriter.append(DataWriter.java:61)
at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:67)
at com.google.cloud.bigquery.storage.v1.ConnectionWorker$1.run(ConnectionWorker.java:233)

Caused by: com.google.cloud.bigquery.storage.v1.Exceptions$StreamWriterClosedException: FAILED_PRECONDITION: Connection is closed due to com.google.api.gax.rpc.InternalException: io.grpc.StatusRuntimeException: INTERNAL: Internal error encountered. Entity: projects/project_name/datasets/dataset_name/tables/table_name/_default
at com.google.cloud.bigquery.storage.v1.ConnectionWorker.appendInternal(ConnectionWorker.java:309)
at com.google.cloud.bigquery.storage.v1.JsonStreamWriter.append(JsonStreamWriter.java:113)
at com.google.api.core.ApiFutures.addCallback(ApiFutures.java:62)
at com.google.api.core.SettableApiFuture.setException(SettableApiFuture.java:51)
at com.google.cloud.bigquery.storage.v1.ConnectionWorker.appendLoop(ConnectionWorker.java:515)
at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1132)
at com.google.api.core.AbstractApiFuture$InternalSettableFuture.setException(AbstractApiFuture.java:94)
at com.google.cloud.bigquery.storage.v1.ConnectionWorker.append(ConnectionWorker.java:267)
at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:67)
at com.google.common.util.concurrent.AbstractFuture.addListener(AbstractFuture.java:761)
at bq.DataWriter$AppendCompleteCallback.onFailure(DataWriter.java:109)
at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1132)
at bq.DataWriter$AppendCompleteCallback.onFailure(DataWriter.java:123)
at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:31)
at com.google.cloud.bigquery.storage.v1.StreamWriter.append(StreamWriter.java:354)
at com.google.cloud.bigquery.storage.v1.ConnectionWorker.access$000(ConnectionWorker.java:58)

Hi @SubhamSinghal,
Thanks for the information. The issue has been identified and we are working on a fix. There are no action items required from your side to fix this.
Thanks for your patience.

Hi @SubhamSinghal ,
While we are working on the fix, retrying should reduce the frequency of the Failed Precondition errors.