Skip to content

Commit 3979862

Browse files
fix: avoid NullPointerException in BigQuery.create() when the duplicated job cannot be re-fetched
The duplicate-job-id handler dereferences the getJob(...) re-fetch unconditionally, but getJob returns null when the job cannot be seen - most commonly a job outside the US multi-region looked up through a JobId that carries no location. Guard it and fall through to the original Already Exists exception, as the random-id branch below already does. Fixes #14025
1 parent a403703 commit 3979862

2 files changed

Lines changed: 45 additions & 12 deletions

File tree

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

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -608,18 +608,20 @@ public com.google.api.services.bigquery.model.Job call() throws IOException {
608608
// If the Job ALREADY EXISTS, retrieve it.
609609
Job job = this.getJob(jobInfo.getJobId(), JobOption.fields(JobField.STATISTICS));
610610

611-
long jobCreationTime = job.getStatistics().getCreationTime();
612-
long jobMinStaleTime = System.currentTimeMillis();
613-
long jobMaxStaleTime =
614-
java.time.Instant.ofEpochMilli(jobMinStaleTime)
615-
.minus(1, java.time.temporal.ChronoUnit.DAYS)
616-
.toEpochMilli();
617-
618-
// Only return the job if it has been created in the past 24 hours.
619-
// This is assuming any job older than 24 hours is a valid duplicate JobID
620-
// and not a false positive like b/290419183
621-
if (jobCreationTime >= jobMaxStaleTime && jobCreationTime <= jobMinStaleTime) {
622-
return job;
611+
if (job != null) {
612+
long jobCreationTime = job.getStatistics().getCreationTime();
613+
long jobMinStaleTime = System.currentTimeMillis();
614+
long jobMaxStaleTime =
615+
java.time.Instant.ofEpochMilli(jobMinStaleTime)
616+
.minus(1, java.time.temporal.ChronoUnit.DAYS)
617+
.toEpochMilli();
618+
619+
// Only return the job if it has been created in the past 24 hours.
620+
// This is assuming any job older than 24 hours is a valid duplicate JobID
621+
// and not a false positive like b/290419183
622+
if (jobCreationTime >= jobMaxStaleTime && jobCreationTime <= jobMinStaleTime) {
623+
return job;
624+
}
623625
}
624626
}
625627
}

java-bigquery/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/BigQueryImplTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2144,6 +2144,37 @@ void testCreateJobTryGetNotRandom() throws IOException {
21442144
any(String.class), eq(id), eq((String) null), eq(withStatisticOption));
21452145
}
21462146

2147+
@Test
2148+
void testCreateJobTryGetNotRandomJobNotFound() throws IOException {
2149+
Map<BigQueryRpc.Option, ?> withStatisticOption = optionMap(JobOption.fields(STATISTICS));
2150+
final String id = "testCreateJobTryGet-id";
2151+
String query = "SELECT * in FOO";
2152+
2153+
when(bigqueryRpcMock.createSkipExceptionTranslation(
2154+
jobCapture.capture(), eq(EMPTY_RPC_OPTIONS)))
2155+
.thenThrow(
2156+
new BigQueryException(
2157+
409,
2158+
"already exists, for some reason",
2159+
new RuntimeException("Already Exists: Job")));
2160+
when(bigqueryRpcMock.getJobSkipExceptionTranslation(
2161+
any(String.class), eq(id), eq((String) null), eq(withStatisticOption)))
2162+
.thenThrow(new BigQueryException(404, "Job not found"));
2163+
2164+
bigquery = options.getService();
2165+
BigQueryException exception =
2166+
Assertions.assertThrows(
2167+
BigQueryException.class,
2168+
() ->
2169+
((BigQueryImpl) bigquery)
2170+
.create(JobInfo.of(JobId.of(id), QueryJobConfiguration.of(query))));
2171+
assertEquals(409, exception.getCode());
2172+
assertEquals("already exists, for some reason", exception.getMessage());
2173+
verify(bigqueryRpcMock)
2174+
.getJobSkipExceptionTranslation(
2175+
any(String.class), eq(id), eq((String) null), eq(withStatisticOption));
2176+
}
2177+
21472178
@Test
21482179
void testCreateJobWithProjectId() throws IOException {
21492180
JobInfo jobInfo =

0 commit comments

Comments
 (0)