Skip to content

Commit ac9b809

Browse files
(fix) Parse the startingTimestamp at api level and not at service level (#200)
1 parent 79c1eab commit ac9b809

File tree

13 files changed

+86
-70
lines changed

13 files changed

+86
-70
lines changed

server/app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ tasks.jacocoTestCoverageVerification {
129129
violationRules {
130130
rule {
131131
limit {
132-
minimum = BigDecimal.valueOf(0.76)
132+
minimum = BigDecimal.valueOf(0.75)
133133
}
134134
}
135135
}

server/app/src/main/java/io/whitefox/api/deltasharing/server/DeltaSharesApiImpl.java

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,34 +69,41 @@ public Response getTableMetadata(
6969
String share,
7070
String schema,
7171
String table,
72-
String startingTimestamp,
72+
String startingTimestampStr,
7373
String deltaSharingCapabilities) {
7474
return wrapExceptions(
75-
() -> optionalToNotFound(
76-
deltaSharesService.getTableMetadata(share, schema, table, startingTimestamp),
77-
m -> optionalToNotFound(
78-
deltaSharesService.getTableVersion(share, schema, table, startingTimestamp),
79-
v -> Response.ok(
80-
tableResponseSerializer.serialize(DeltaMappers.toTableResponseMetadata(m)),
81-
ndjsonMediaType)
82-
.status(Response.Status.OK.getStatusCode())
83-
.header(DELTA_TABLE_VERSION_HEADER, String.valueOf(v))
84-
.header(
85-
DELTA_SHARE_CAPABILITIES_HEADER,
86-
getResponseFormatHeader(
87-
DeltaMappers.toHeaderCapabilitiesMap(deltaSharingCapabilities)))
88-
.build())),
75+
() -> {
76+
var startingTimestamp = parseTimestamp(startingTimestampStr);
77+
return optionalToNotFound(
78+
deltaSharesService.getTableMetadata(share, schema, table, startingTimestamp),
79+
m -> optionalToNotFound(
80+
deltaSharesService.getTableVersion(share, schema, table, startingTimestamp),
81+
v -> Response.ok(
82+
tableResponseSerializer.serialize(
83+
DeltaMappers.toTableResponseMetadata(m)),
84+
ndjsonMediaType)
85+
.status(Response.Status.OK.getStatusCode())
86+
.header(DELTA_TABLE_VERSION_HEADER, String.valueOf(v))
87+
.header(
88+
DELTA_SHARE_CAPABILITIES_HEADER,
89+
getResponseFormatHeader(
90+
DeltaMappers.toHeaderCapabilitiesMap(deltaSharingCapabilities)))
91+
.build()));
92+
},
8993
exceptionToResponse);
9094
}
9195

9296
@Override
9397
public Response getTableVersion(
94-
String share, String schema, String table, String startingTimestamp) {
98+
String share, String schema, String table, String startingTimestampStr) {
9599

96100
return wrapExceptions(
97-
() -> optionalToNotFound(
98-
deltaSharesService.getTableVersion(share, schema, table, startingTimestamp),
99-
t -> Response.ok().header(DELTA_TABLE_VERSION_HEADER, t).build()),
101+
() -> {
102+
var startingTimestamp = parseTimestamp(startingTimestampStr);
103+
return optionalToNotFound(
104+
deltaSharesService.getTableVersion(share, schema, table, startingTimestamp),
105+
t -> Response.ok().header(DELTA_TABLE_VERSION_HEADER, t).build());
106+
},
100107
exceptionToResponse);
101108
}
102109

server/app/src/main/java/io/whitefox/api/server/ApiUtils.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
import io.whitefox.core.services.exceptions.AlreadyExists;
88
import io.whitefox.core.services.exceptions.NotFound;
99
import jakarta.ws.rs.core.Response;
10+
import java.sql.Timestamp;
11+
import java.time.OffsetDateTime;
12+
import java.time.format.DateTimeFormatter;
13+
import java.time.format.DateTimeParseException;
1014
import java.util.Map;
1115
import java.util.Optional;
1216
import java.util.function.Function;
@@ -33,6 +37,12 @@ public interface ApiUtils extends DeltaHeaders {
3337
.errorCode("NOT FOUND")
3438
.message(ExceptionUtil.generateStackTrace(t)))
3539
.build();
40+
} else if (t instanceof DateTimeParseException) {
41+
return Response.status(Response.Status.BAD_REQUEST)
42+
.entity(new CommonErrorResponse()
43+
.errorCode("BAD REQUEST - timestamp provided is not formatted correctly")
44+
.message(ExceptionUtil.generateStackTrace(t)))
45+
.build();
3646
} else {
3747
return Response.status(Response.Status.BAD_GATEWAY)
3848
.entity(new CommonErrorResponse()
@@ -79,4 +89,11 @@ default Principal getRequestPrincipal() {
7989
default Principal resolvePrincipal(String s) {
8090
return new Principal(s);
8191
}
92+
93+
default Optional<Timestamp> parseTimestamp(String timestamp) {
94+
return Optional.ofNullable(timestamp)
95+
.map(ts -> new Timestamp(OffsetDateTime.parse(ts, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
96+
.toInstant()
97+
.toEpochMilli()));
98+
}
8299
}

server/app/src/test/java/io/whitefox/api/deltasharing/server/DeltaSharesApiImplTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ public void getTableVersionBadTimestamp() {
349349
"default",
350350
"table1")
351351
.then()
352-
.statusCode(502);
352+
.statusCode(Response.Status.BAD_REQUEST.getStatusCode());
353353
}
354354

355355
@DisabledOnOs(OS.WINDOWS)

server/core/src/main/java/io/whitefox/core/services/DeltaSharedTable.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
import io.delta.standalone.Snapshot;
55
import io.whitefox.core.*;
66
import java.sql.Timestamp;
7-
import java.time.OffsetDateTime;
8-
import java.time.format.DateTimeFormatter;
97
import java.util.Optional;
108
import java.util.stream.Collectors;
119

@@ -54,7 +52,7 @@ public static DeltaSharedTable of(SharedTable sharedTable) {
5452
return of(sharedTable, TableSchemaConverter.INSTANCE, new HadoopConfigBuilder());
5553
}
5654

57-
public Optional<Metadata> getMetadata(Optional<String> startingTimestamp) {
55+
public Optional<Metadata> getMetadata(Optional<Timestamp> startingTimestamp) {
5856
return getSnapshot(startingTimestamp).map(this::metadataFromSnapshot);
5957
}
6058

@@ -74,7 +72,7 @@ private Metadata metadataFromSnapshot(Snapshot snapshot) {
7472
);
7573
}
7674

77-
public Optional<Long> getTableVersion(Optional<String> startingTimestamp) {
75+
public Optional<Long> getTableVersion(Optional<Timestamp> startingTimestamp) {
7876
return getSnapshot(startingTimestamp).map(Snapshot::getVersion);
7977
}
8078

@@ -106,9 +104,8 @@ public ReadTableResultToBeSigned queryTable(ReadTableRequest readTableRequest) {
106104
snapshot.getVersion());
107105
}
108106

109-
private Optional<Snapshot> getSnapshot(Optional<String> startingTimestamp) {
107+
private Optional<Snapshot> getSnapshot(Optional<Timestamp> startingTimestamp) {
110108
return startingTimestamp
111-
.map(this::getTimestamp)
112109
.map(Timestamp::getTime)
113110
.map(this::getSnapshotForTimestampAsOf)
114111
.orElse(Optional.of(getSnapshot()));
@@ -131,12 +128,6 @@ private String location() {
131128
return location.replaceAll("/+$", "");
132129
}
133130

134-
private Timestamp getTimestamp(String timestamp) {
135-
return new Timestamp(OffsetDateTime.parse(timestamp, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
136-
.toInstant()
137-
.toEpochMilli());
138-
}
139-
140131
public static class DeltaShareTableFormat {
141132
public static final String RESPONSE_FORMAT_PARQUET = "parquet";
142133
public static final String RESPONSE_FORMAT_DELTA = "delta";

server/core/src/main/java/io/whitefox/core/services/DeltaSharesService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@
55
import io.whitefox.core.Schema;
66
import io.whitefox.core.Share;
77
import io.whitefox.core.SharedTable;
8+
import java.sql.Timestamp;
89
import java.util.List;
910
import java.util.Optional;
1011

1112
public interface DeltaSharesService {
1213

1314
Optional<Long> getTableVersion(
14-
String share, String schema, String table, String startingTimestamp);
15+
String share, String schema, String table, Optional<Timestamp> startingTimestamp);
1516

1617
ContentAndToken<List<Share>> listShares(
1718
Optional<ContentAndToken.Token> nextPageToken, Optional<Integer> maxResults);
1819

1920
Optional<Metadata> getTableMetadata(
20-
String share, String schema, String table, String startingTimestamp);
21+
String share, String schema, String table, Optional<Timestamp> startingTimestamp);
2122

2223
Optional<ContentAndToken<List<Schema>>> listSchemas(
2324
String share, Optional<ContentAndToken.Token> nextPageToken, Optional<Integer> maxResults);

server/core/src/main/java/io/whitefox/core/services/DeltaSharesServiceImpl.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.whitefox.persistence.StorageManager;
66
import jakarta.enterprise.context.ApplicationScoped;
77
import jakarta.inject.Inject;
8+
import java.sql.Timestamp;
89
import java.util.List;
910
import java.util.Optional;
1011
import java.util.stream.Collectors;
@@ -33,13 +34,13 @@ public DeltaSharesServiceImpl(
3334

3435
@Override
3536
public Optional<Long> getTableVersion(
36-
String share, String schema, String table, String startingTimestamp) {
37+
String share, String schema, String table, Optional<Timestamp> startingTimestamp) {
3738
return storageManager
3839
.getSharedTable(share, schema, table)
3940
.map(t -> tableLoaderFactory
4041
.newTableLoader(t.internalTable())
4142
.loadTable(t)
42-
.getTableVersion(Optional.ofNullable(startingTimestamp)))
43+
.getTableVersion(startingTimestamp))
4344
.orElse(Optional.empty());
4445
}
4546

@@ -60,11 +61,11 @@ public ContentAndToken<List<Share>> listShares(
6061

6162
@Override
6263
public Optional<Metadata> getTableMetadata(
63-
String share, String schema, String table, String startingTimestamp) {
64+
String share, String schema, String table, Optional<Timestamp> startingTimestamp) {
6465
return storageManager.getSharedTable(share, schema, table).flatMap(t -> tableLoaderFactory
6566
.newTableLoader(t.internalTable())
6667
.loadTable(t)
67-
.getMetadata(Optional.ofNullable(startingTimestamp)));
68+
.getMetadata(startingTimestamp));
6869
}
6970

7071
@Override

server/core/src/main/java/io/whitefox/core/services/IcebergSharedTable.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import io.whitefox.core.ReadTableResultToBeSigned;
66
import io.whitefox.core.TableSchema;
77
import java.sql.Timestamp;
8-
import java.time.OffsetDateTime;
9-
import java.time.format.DateTimeFormatter;
108
import java.util.Optional;
119
import java.util.stream.Collectors;
1210
import org.apache.commons.lang3.NotImplementedException;
@@ -34,7 +32,7 @@ public static IcebergSharedTable of(Table icebergTable) {
3432
return new IcebergSharedTable(icebergTable, new TableSchemaConverter());
3533
}
3634

37-
public Optional<Metadata> getMetadata(Optional<String> startingTimestamp) {
35+
public Optional<Metadata> getMetadata(Optional<Timestamp> startingTimestamp) {
3836
return getSnapshot(startingTimestamp).map(this::getMetadataFromSnapshot);
3937
}
4038

@@ -56,9 +54,8 @@ private Metadata getMetadataFromSnapshot(Snapshot snapshot) {
5654
);
5755
}
5856

59-
private Optional<Snapshot> getSnapshot(Optional<String> startingTimestamp) {
57+
private Optional<Snapshot> getSnapshot(Optional<Timestamp> startingTimestamp) {
6058
return startingTimestamp
61-
.map(this::getTimestamp)
6259
.map(Timestamp::getTime)
6360
.map(this::getSnapshotForTimestampAsOf)
6461
.orElseGet(() -> Optional.ofNullable(icebergTable.currentSnapshot()));
@@ -73,14 +70,8 @@ private Optional<Snapshot> getSnapshotForTimestampAsOf(long l) {
7370
}
7471
}
7572

76-
private Timestamp getTimestamp(String timestamp) {
77-
return new Timestamp(OffsetDateTime.parse(timestamp, DateTimeFormatter.ISO_OFFSET_DATE_TIME)
78-
.toInstant()
79-
.toEpochMilli());
80-
}
81-
8273
@Override
83-
public Optional<Long> getTableVersion(Optional<String> startingTimestamp) {
74+
public Optional<Long> getTableVersion(Optional<Timestamp> startingTimestamp) {
8475
return getSnapshot(startingTimestamp).map(Snapshot::sequenceNumber);
8576
}
8677

server/core/src/main/java/io/whitefox/core/services/InternalSharedTable.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
import io.whitefox.core.Metadata;
44
import io.whitefox.core.ReadTableRequest;
55
import io.whitefox.core.ReadTableResultToBeSigned;
6+
import java.sql.Timestamp;
67
import java.util.Optional;
78

89
public interface InternalSharedTable {
910

10-
Optional<Metadata> getMetadata(Optional<String> startingTimestamp);
11+
Optional<Metadata> getMetadata(Optional<Timestamp> startingTimestamp);
1112

12-
Optional<Long> getTableVersion(Optional<String> startingTimestamp);
13+
Optional<Long> getTableVersion(Optional<Timestamp> startingTimestamp);
1314

1415
ReadTableResultToBeSigned queryTable(ReadTableRequest readTableRequest);
1516
}

server/core/src/test/java/io/whitefox/core/services/DeltaShareServiceTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ public void getDeltaTableMetadata() {
202202
StorageManager storageManager = new InMemoryStorageManager(shares);
203203
DeltaSharesService deltaSharesService =
204204
new DeltaSharesServiceImpl(storageManager, 100, tableLoaderFactory, fileSignerFactory);
205-
var tableMetadata = deltaSharesService.getTableMetadata("name", "default", "table1", null);
205+
var tableMetadata =
206+
deltaSharesService.getTableMetadata("name", "default", "table1", Optional.empty());
206207
Assertions.assertTrue(tableMetadata.isPresent());
207208
Assertions.assertEquals(
208209
"56d48189-cdbc-44f2-9b0e-2bded4c79ed7", tableMetadata.get().id());
@@ -223,7 +224,8 @@ public void tableMetadataNotFound() {
223224
StorageManager storageManager = new InMemoryStorageManager(shares);
224225
DeltaSharesService deltaSharesService =
225226
new DeltaSharesServiceImpl(storageManager, 100, tableLoaderFactory, fileSignerFactory);
226-
var resultTable = deltaSharesService.getTableMetadata("name", "default", "tableNotFound", null);
227+
var resultTable =
228+
deltaSharesService.getTableMetadata("name", "default", "tableNotFound", Optional.empty());
227229
Assertions.assertTrue(resultTable.isEmpty());
228230
}
229231
}

0 commit comments

Comments
 (0)