Skip to content

Commit 67a07ea

Browse files
feat: adds Exception handling to handle ALREADY EXISTS error (#2788)
* feat: adds Exception handling to handle ALREADy EXISTS error * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * chore: add more conditions * chore: format * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * chore: don't ad extra dependency * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * nit * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot <gcf-owl-bot[bot]@users.noreply.github.com>
1 parent abc0ddf commit 67a07ea

File tree

3 files changed

+63
-8
lines changed

3 files changed

+63
-8
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,20 @@ If you are using Maven without the BOM, add this to your dependencies:
5353
If you are using Gradle 5.x or later, add this to your dependencies:
5454

5555
```Groovy
56-
implementation platform('com.google.cloud:libraries-bom:26.18.0')
56+
implementation platform('com.google.cloud:libraries-bom:26.19.0')
5757
5858
implementation 'com.google.cloud:google-cloud-bigquery'
5959
```
6060
If you are using Gradle without BOM, add this to your dependencies:
6161

6262
```Groovy
63-
implementation 'com.google.cloud:google-cloud-bigquery:2.30.0'
63+
implementation 'com.google.cloud:google-cloud-bigquery:2.30.1'
6464
```
6565

6666
If you are using SBT, add this to your dependencies:
6767

6868
```Scala
69-
libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "2.30.0"
69+
libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "2.30.1"
7070
```
7171
<!-- {x-version-update-end} -->
7272

@@ -351,7 +351,7 @@ Java is a registered trademark of Oracle and/or its affiliates.
351351
[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-bigquery/java11.html
352352
[stability-image]: https://img.shields.io/badge/stability-stable-green
353353
[maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-bigquery.svg
354-
[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-bigquery/2.30.0
354+
[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-bigquery/2.30.1
355355
[authentication]: https://github.com/googleapis/google-cloud-java#authentication
356356
[auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
357357
[predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles

google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryImpl.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@
5555
import java.util.List;
5656
import java.util.Map;
5757
import java.util.concurrent.Callable;
58+
import java.util.regex.Matcher;
59+
import java.util.regex.Pattern;
5860
import org.checkerframework.checker.nullness.qual.NonNull;
61+
import org.threeten.bp.Instant;
62+
import org.threeten.bp.temporal.ChronoUnit;
5963

6064
final class BigQueryImpl extends BaseService<BigQueryOptions> implements BigQuery {
6165

@@ -422,15 +426,38 @@ public com.google.api.services.bigquery.model.Job call() {
422426
}
423427

424428
if (!idRandom) {
429+
if (createException instanceof BigQueryException && createException.getCause() != null) {
430+
431+
/*GoogleJsonResponseException createExceptionCause =
432+
(GoogleJsonResponseException) createException.getCause();*/
433+
434+
Pattern pattern = Pattern.compile(".*Already.*Exists:.*Job.*", Pattern.CASE_INSENSITIVE);
435+
Matcher matcher = pattern.matcher(createException.getCause().getMessage());
436+
437+
if (matcher.find()) {
438+
// If the Job ALREADY EXISTS, retrieve it.
439+
Job job = this.getJob(jobInfo.getJobId());
440+
441+
long jobCreationTime = job.getStatistics().getCreationTime();
442+
long jobMinStaleTime = System.currentTimeMillis();
443+
long jobMaxStaleTime =
444+
Instant.ofEpochMilli(jobMinStaleTime).minus(1, ChronoUnit.DAYS).toEpochMilli();
445+
446+
// Only return the job if it has been created in the past 24 hours.
447+
// This is assuming any job older than 24 hours is a valid duplicate JobID
448+
// and not a false positive like b/290419183
449+
if (jobCreationTime >= jobMaxStaleTime && jobCreationTime <= jobMinStaleTime) {
450+
return job;
451+
}
452+
}
453+
}
425454
throw createException;
426455
}
427456

428457
// If create RPC fails, it's still possible that the job has been successfully
429-
// created,
430-
// and get might work.
458+
// created, and get might work.
431459
// We can only do this if we randomly generated the ID. Otherwise we might
432-
// mistakenly
433-
// fetch a job created by someone else.
460+
// mistakenly fetch a job created by someone else.
434461
Job job;
435462
try {
436463
job = getJob(finalJobId[0]);

google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/it/ITBigQueryTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import com.google.cloud.bigquery.InsertAllRequest.RowToInsert;
8484
import com.google.cloud.bigquery.InsertAllResponse;
8585
import com.google.cloud.bigquery.Job;
86+
import com.google.cloud.bigquery.JobConfiguration;
8687
import com.google.cloud.bigquery.JobId;
8788
import com.google.cloud.bigquery.JobInfo;
8889
import com.google.cloud.bigquery.JobStatistics;
@@ -6101,4 +6102,31 @@ public void testForeignKeysUpdate() {
61016102
bigquery.delete(tableIdPk2);
61026103
}
61036104
}
6105+
6106+
@Test
6107+
public void testAlreadyExistJobExceptionHandling() throws InterruptedException {
6108+
String query =
6109+
"SELECT TimestampField, StringField, BooleanField FROM "
6110+
+ DATASET
6111+
+ "."
6112+
+ TABLE_ID.getTable();
6113+
JobId jobId = JobId.newBuilder().setRandomJob().build();
6114+
6115+
JobConfiguration queryJobConfiguration = QueryJobConfiguration.newBuilder(query).build();
6116+
// Creating the job with the explicit jobID
6117+
bigquery.create(JobInfo.of(jobId, queryJobConfiguration));
6118+
// Calling the query method with the job that has already been created.
6119+
// This should throw ALREADY_EXISTS error without the exception handling added
6120+
// or if the job is older than 24 hours.
6121+
try {
6122+
bigquery.query(QueryJobConfiguration.newBuilder(query).build(), jobId);
6123+
// Test succeeds if Exception is not thrown and code flow reaches this statement.
6124+
assertTrue(true);
6125+
} catch (BigQueryException ex) {
6126+
// test fails if an exception is thrown
6127+
if (ex.getCause() != null && ex.getCause().getMessage().contains("Already Exists: Job")) {
6128+
fail("Already exists error should not be thrown");
6129+
}
6130+
}
6131+
}
61046132
}

0 commit comments

Comments
 (0)