Skip to content

Commit 20b8756

Browse files
authored
[DE-771] Refactoring serde context (#555)
* added SerdeContext.EMPTY * make SerdeContext#getStreamTransactionId() return Optional * thread local SerdeContextHolder * renamed SerdeContext to RequestContext * RequestContextHolder.runWithCtx * changed RequestContext package * fixed RequestContext.EMPTY * added RequestContextHolder safety checks * RequestContextHolder: support re-entrant invocations
1 parent 7605325 commit 20b8756

36 files changed

+319
-240
lines changed

Diff for: core/src/main/java/com/arangodb/RequestContext.java

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.arangodb;
2+
3+
import com.arangodb.internal.RequestContextImpl;
4+
5+
import java.util.Optional;
6+
7+
/**
8+
* Context holding information about the current request and response.
9+
*/
10+
public interface RequestContext {
11+
12+
RequestContext EMPTY = new RequestContextImpl();
13+
14+
/**
15+
* @return the stream transaction id of the request (if any) or {@code null}
16+
*/
17+
Optional<String> getStreamTransactionId();
18+
}

Diff for: core/src/main/java/com/arangodb/arch/NoRawTypesInspection.java

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
/**
99
* Skip invoking {@code JavaType#getAllInvolvedRawTypes()} on the target class during arch tests.
1010
* Prevents StackOverflowError caused by <a href="https://github.com/TNG/ArchUnit/issues/1237">this</a>.
11+
* FIXME: remove this when <a href="https://github.com/TNG/ArchUnit/issues/1237">this</a> is fixed and released
1112
*/
1213
@Retention(RetentionPolicy.CLASS)
1314
@Target(ElementType.TYPE)

Diff for: core/src/main/java/com/arangodb/internal/ArangoExecutor.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import com.arangodb.internal.config.ArangoConfig;
2626
import com.arangodb.internal.net.CommunicationProtocol;
2727
import com.arangodb.internal.serde.InternalSerde;
28-
import com.arangodb.serde.SerdeContext;
2928

3029
import java.io.IOException;
3130
import java.lang.reflect.Type;
@@ -59,8 +58,8 @@ public void setJwt(String jwt) {
5958
protocol.setJwt(jwt);
6059
}
6160

62-
protected <T> T createResult(final Type type, final InternalResponse response, final SerdeContext ctx) {
63-
return serde.deserialize(response.getBody(), type, ctx);
61+
protected <T> T createResult(final Type type, final InternalResponse response) {
62+
return serde.deserialize(response.getBody(), type);
6463
}
6564

6665
protected final void interceptResponse(InternalResponse response) {
@@ -80,6 +79,6 @@ public QueueTimeMetrics getQueueTimeMetrics() {
8079
}
8180

8281
public interface ResponseDeserializer<T> {
83-
T deserialize(InternalResponse response, SerdeContext ctx);
82+
T deserialize(InternalResponse response);
8483
}
8584
}

Diff for: core/src/main/java/com/arangodb/internal/ArangoExecutorAsync.java

+8-9
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@
2424
import com.arangodb.internal.config.ArangoConfig;
2525
import com.arangodb.internal.net.CommunicationProtocol;
2626
import com.arangodb.internal.net.HostHandle;
27-
import com.arangodb.internal.serde.SerdeUtils;
28-
import com.arangodb.serde.SerdeContext;
27+
import com.arangodb.RequestContext;
2928

3029
import java.lang.reflect.Type;
3130
import java.util.concurrent.CompletableFuture;
@@ -50,7 +49,7 @@ public <T> CompletableFuture<T> execute(final Supplier<InternalRequest> requestS
5049
}
5150

5251
public <T> CompletableFuture<T> execute(final Supplier<InternalRequest> requestSupplier, final Type type, final HostHandle hostHandle) {
53-
return execute(requestSupplier, (response, ctx) -> createResult(type, response, ctx), hostHandle);
52+
return execute(requestSupplier, (response) -> createResult(type, response), hostHandle);
5453
}
5554

5655
public <T> CompletableFuture<T> execute(final Supplier<InternalRequest> requestSupplier, final ResponseDeserializer<T> responseDeserializer) {
@@ -66,14 +65,15 @@ public <T> CompletableFuture<T> execute(
6665
.thenApply(Supplier::get)
6766
.thenCompose(request -> protocol
6867
.executeAsync(interceptRequest(request), hostHandle)
69-
.thenApply(resp -> new ResponseWithContext(resp, SerdeUtils.createSerdeContext(request)))
68+
.thenApply(resp -> new ResponseWithRequest(resp, new RequestContextImpl(request)))
7069
)
7170
.handle((r, e) -> {
7271
if (e != null) {
7372
throw ArangoDBException.of(e);
7473
} else {
7574
interceptResponse(r.response);
76-
return responseDeserializer.deserialize(r.response, r.context);
75+
return RequestContextHolder.INSTANCE.runWithCtx(r.context, () ->
76+
responseDeserializer.deserialize(r.response));
7777
}
7878
});
7979

@@ -84,15 +84,14 @@ public <T> CompletableFuture<T> execute(
8484
}
8585
}
8686

87-
private static class ResponseWithContext {
87+
private static class ResponseWithRequest {
8888
final InternalResponse response;
89-
final SerdeContext context;
89+
final RequestContext context;
9090

91-
ResponseWithContext(InternalResponse response, SerdeContext context) {
91+
ResponseWithRequest(InternalResponse response, RequestContext context) {
9292
this.response = response;
9393
this.context = context;
9494
}
9595
}
9696

97-
9897
}

Diff for: core/src/main/java/com/arangodb/internal/ArangoExecutorSync.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.arangodb.internal.config.ArangoConfig;
2424
import com.arangodb.internal.net.CommunicationProtocol;
2525
import com.arangodb.internal.net.HostHandle;
26-
import com.arangodb.internal.serde.SerdeUtils;
2726

2827
import java.lang.reflect.Type;
2928

@@ -41,7 +40,7 @@ public <T> T execute(final InternalRequest request, final Type type) {
4140
}
4241

4342
public <T> T execute(final InternalRequest request, final Type type, final HostHandle hostHandle) {
44-
return execute(request, (response, ctx) -> createResult(type, response, ctx), hostHandle);
43+
return execute(request, (response) -> createResult(type, response), hostHandle);
4544
}
4645

4746
public <T> T execute(final InternalRequest request, final ResponseDeserializer<T> responseDeserializer) {
@@ -55,7 +54,8 @@ public <T> T execute(
5554

5655
final InternalResponse response = protocol.execute(interceptRequest(request), hostHandle);
5756
interceptResponse(response);
58-
return responseDeserializer.deserialize(response, SerdeUtils.createSerdeContext(request));
57+
return RequestContextHolder.INSTANCE.runWithCtx(new RequestContextImpl(request), () ->
58+
responseDeserializer.deserialize(response));
5959
}
6060

6161
}

Diff for: core/src/main/java/com/arangodb/internal/InternalArangoCollection.java

+23-23
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ private InternalRequest createInsertDocumentRequest(final DocumentCreateOptions
110110
}
111111

112112
protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentCreateEntity<T>>> insertDocumentsResponseDeserializer(Class<T> userDataClass) {
113-
return (response, ctx) -> {
113+
return (response) -> {
114114
final MultiDocumentEntity<DocumentCreateEntity<T>> multiDocument = new MultiDocumentEntity<>();
115115
final List<DocumentCreateEntity<T>> docs = new ArrayList<>();
116116
final List<ErrorEntity> errors = new ArrayList<>();
@@ -119,12 +119,12 @@ protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentCreateEntity<T>>>
119119
for (final JsonNode next : body) {
120120
JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME);
121121
if (isError != null && isError.booleanValue()) {
122-
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class, ctx);
122+
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class);
123123
errors.add(error);
124124
documentsAndErrors.add(error);
125125
} else {
126126
Type type = constructParametricType(DocumentCreateEntity.class, userDataClass);
127-
final DocumentCreateEntity<T> doc = getSerde().deserialize(next, type, ctx);
127+
final DocumentCreateEntity<T> doc = getSerde().deserialize(next, type);
128128
docs.add(doc);
129129
documentsAndErrors.add(doc);
130130
}
@@ -168,7 +168,7 @@ protected InternalRequest getDocumentRequest(final String key, final DocumentRea
168168
}
169169

170170
protected <T> ResponseDeserializer<T> getDocumentResponseDeserializer(final Class<T> type) {
171-
return (response, ctx) -> getSerde().deserializeUserData(response.getBody(), type, ctx);
171+
return (response) -> getSerde().deserializeUserData(response.getBody(), type);
172172
}
173173

174174
protected InternalRequest getDocumentsRequest(final Iterable<String> keys, final DocumentReadOptions options) {
@@ -186,7 +186,7 @@ protected InternalRequest getDocumentsRequest(final Iterable<String> keys, final
186186

187187
protected <T> ResponseDeserializer<MultiDocumentEntity<T>> getDocumentsResponseDeserializer(
188188
final Class<T> type) {
189-
return (response, ctx) -> {
189+
return (response) -> {
190190
final MultiDocumentEntity<T> multiDocument = new MultiDocumentEntity<>();
191191
boolean potentialDirtyRead = Boolean.parseBoolean(response.getMeta("X-Arango-Potential-Dirty-Read"));
192192
multiDocument.setPotentialDirtyRead(potentialDirtyRead);
@@ -197,11 +197,11 @@ protected <T> ResponseDeserializer<MultiDocumentEntity<T>> getDocumentsResponseD
197197
for (final JsonNode next : body) {
198198
JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME);
199199
if (isError != null && isError.booleanValue()) {
200-
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class, ctx);
200+
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class);
201201
errors.add(error);
202202
documentsAndErrors.add(error);
203203
} else {
204-
final T doc = getSerde().deserializeUserData(getSerde().serialize(next), type, ctx);
204+
final T doc = getSerde().deserializeUserData(getSerde().serialize(next), type);
205205
docs.add(doc);
206206
documentsAndErrors.add(doc);
207207
}
@@ -249,7 +249,7 @@ private InternalRequest createReplaceDocumentRequest(final DocumentReplaceOption
249249

250250
protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentUpdateEntity<T>>> replaceDocumentsResponseDeserializer(
251251
final Class<T> returnType) {
252-
return (response, ctx) -> {
252+
return (response) -> {
253253
final MultiDocumentEntity<DocumentUpdateEntity<T>> multiDocument = new MultiDocumentEntity<>();
254254
final List<DocumentUpdateEntity<T>> docs = new ArrayList<>();
255255
final List<ErrorEntity> errors = new ArrayList<>();
@@ -258,12 +258,12 @@ protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentUpdateEntity<T>>>
258258
for (final JsonNode next : body) {
259259
JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME);
260260
if (isError != null && isError.booleanValue()) {
261-
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class, ctx);
261+
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class);
262262
errors.add(error);
263263
documentsAndErrors.add(error);
264264
} else {
265265
Type type = constructParametricType(DocumentUpdateEntity.class, returnType);
266-
final DocumentUpdateEntity<T> doc = getSerde().deserialize(next, type, ctx);
266+
final DocumentUpdateEntity<T> doc = getSerde().deserialize(next, type);
267267
docs.add(doc);
268268
documentsAndErrors.add(doc);
269269
}
@@ -312,7 +312,7 @@ private InternalRequest createUpdateDocumentRequest(final DocumentUpdateOptions
312312

313313
protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentUpdateEntity<T>>> updateDocumentsResponseDeserializer(
314314
final Class<T> returnType) {
315-
return (response, ctx) -> {
315+
return (response) -> {
316316
final MultiDocumentEntity<DocumentUpdateEntity<T>> multiDocument = new MultiDocumentEntity<>();
317317
final List<DocumentUpdateEntity<T>> docs = new ArrayList<>();
318318
final List<ErrorEntity> errors = new ArrayList<>();
@@ -321,12 +321,12 @@ protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentUpdateEntity<T>>>
321321
for (final JsonNode next : body) {
322322
JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME);
323323
if (isError != null && isError.booleanValue()) {
324-
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class, ctx);
324+
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class);
325325
errors.add(error);
326326
documentsAndErrors.add(error);
327327
} else {
328328
Type type = constructParametricType(DocumentUpdateEntity.class, returnType);
329-
final DocumentUpdateEntity<T> doc = getSerde().deserialize(next, type, ctx);
329+
final DocumentUpdateEntity<T> doc = getSerde().deserialize(next, type);
330330
docs.add(doc);
331331
documentsAndErrors.add(doc);
332332
}
@@ -368,7 +368,7 @@ private InternalRequest createDeleteDocumentRequest(final DocumentDeleteOptions
368368

369369
protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentDeleteEntity<T>>> deleteDocumentsResponseDeserializer(
370370
final Class<T> userDataClass) {
371-
return (response, ctx) -> {
371+
return (response) -> {
372372
final MultiDocumentEntity<DocumentDeleteEntity<T>> multiDocument = new MultiDocumentEntity<>();
373373
final List<DocumentDeleteEntity<T>> docs = new ArrayList<>();
374374
final List<ErrorEntity> errors = new ArrayList<>();
@@ -377,12 +377,12 @@ protected <T> ResponseDeserializer<MultiDocumentEntity<DocumentDeleteEntity<T>>>
377377
for (final JsonNode next : body) {
378378
JsonNode isError = next.get(ArangoResponseField.ERROR_FIELD_NAME);
379379
if (isError != null && isError.booleanValue()) {
380-
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class, ctx);
380+
final ErrorEntity error = getSerde().deserialize(next, ErrorEntity.class);
381381
errors.add(error);
382382
documentsAndErrors.add(error);
383383
} else {
384384
Type type = constructParametricType(DocumentDeleteEntity.class, userDataClass);
385-
final DocumentDeleteEntity<T> doc = getSerde().deserialize(next, type, ctx);
385+
final DocumentDeleteEntity<T> doc = getSerde().deserialize(next, type);
386386
docs.add(doc);
387387
documentsAndErrors.add(doc);
388388
}
@@ -413,7 +413,7 @@ protected InternalRequest deleteIndexRequest(final String id) {
413413
}
414414

415415
protected ResponseDeserializer<String> deleteIndexResponseDeserializer() {
416-
return (response, ctx) -> getSerde().deserialize(response.getBody(), "/id", String.class, ctx);
416+
return (response) -> getSerde().deserialize(response.getBody(), "/id", String.class);
417417
}
418418

419419
private String createIndexId(final String id) {
@@ -495,23 +495,23 @@ protected InternalRequest getIndexesRequest() {
495495
}
496496

497497
protected ResponseDeserializer<Collection<IndexEntity>> getIndexesResponseDeserializer() {
498-
return (response, ctx) -> {
498+
return (response) -> {
499499
Collection<IndexEntity> indexes = new ArrayList<>();
500500
for (JsonNode idx : getSerde().parse(response.getBody(), "/indexes")) {
501501
if (!"inverted".equals(idx.get("type").textValue())) {
502-
indexes.add(getSerde().deserialize(idx, IndexEntity.class, ctx));
502+
indexes.add(getSerde().deserialize(idx, IndexEntity.class));
503503
}
504504
}
505505
return indexes;
506506
};
507507
}
508508

509509
protected ResponseDeserializer<Collection<InvertedIndexEntity>> getInvertedIndexesResponseDeserializer() {
510-
return (response, ctx) -> {
510+
return (response) -> {
511511
Collection<InvertedIndexEntity> indexes = new ArrayList<>();
512512
for (JsonNode idx : getSerde().parse(response.getBody(), "/indexes")) {
513513
if ("inverted".equals(idx.get("type").textValue())) {
514-
indexes.add(getSerde().deserialize(idx, InvertedIndexEntity.class, ctx));
514+
indexes.add(getSerde().deserialize(idx, InvertedIndexEntity.class));
515515
}
516516
}
517517
return indexes;
@@ -583,8 +583,8 @@ protected InternalRequest getPermissionsRequest(final String user) {
583583
}
584584

585585
protected ResponseDeserializer<Permissions> getPermissionsResponseDeserialzer() {
586-
return (response, ctx) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
587-
Permissions.class, ctx);
586+
return (response) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
587+
Permissions.class);
588588
}
589589

590590
}

Diff for: core/src/main/java/com/arangodb/internal/InternalArangoDB.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ protected InternalRequest getServerIdRequest() {
6666
}
6767

6868
protected ResponseDeserializer<ServerRole> getRoleResponseDeserializer() {
69-
return (response, ctx) -> getSerde().deserialize(response.getBody(), "/role", ServerRole.class, ctx);
69+
return (response) -> getSerde().deserialize(response.getBody(), "/role", ServerRole.class);
7070
}
7171

7272
protected ResponseDeserializer<String> getServerIdResponseDeserializer() {
73-
return (response, ctx) -> getSerde().deserialize(response.getBody(), "/id", String.class, ctx);
73+
return (response) -> getSerde().deserialize(response.getBody(), "/id", String.class);
7474
}
7575

7676
protected InternalRequest createDatabaseRequest(final DBCreateOptions options) {
@@ -81,25 +81,25 @@ protected InternalRequest createDatabaseRequest(final DBCreateOptions options) {
8181
}
8282

8383
protected ResponseDeserializer<Boolean> createDatabaseResponseDeserializer() {
84-
return (response, ctx) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
85-
Boolean.class, ctx);
84+
return (response) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
85+
Boolean.class);
8686
}
8787

8888
protected InternalRequest getDatabasesRequest(final String dbName) {
8989
return request(dbName, RequestType.GET, InternalArangoDatabase.PATH_API_DATABASE);
9090
}
9191

9292
protected ResponseDeserializer<Collection<String>> getDatabaseResponseDeserializer() {
93-
return (response, ctx) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
94-
constructListType(String.class), ctx);
93+
return (response) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
94+
constructListType(String.class));
9595
}
9696

9797
protected InternalRequest getAccessibleDatabasesForRequest(final String dbName, final String user) {
9898
return request(dbName, RequestType.GET, PATH_API_USER, user, ArangoRequestParam.DATABASE);
9999
}
100100

101101
protected ResponseDeserializer<Collection<String>> getAccessibleDatabasesForResponseDeserializer() {
102-
return (response, ctx) -> {
102+
return (response) -> {
103103
Iterator<String> names =
104104
getSerde().parse(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER).fieldNames();
105105
final Collection<String> dbs = new ArrayList<>();
@@ -136,8 +136,8 @@ protected InternalRequest getUserRequest(final String dbName, final String user)
136136
}
137137

138138
protected ResponseDeserializer<Collection<UserEntity>> getUsersResponseDeserializer() {
139-
return (response, ctx) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
140-
constructListType(UserEntity.class), ctx);
139+
return (response) -> getSerde().deserialize(response.getBody(), ArangoResponseField.RESULT_JSON_POINTER,
140+
constructListType(UserEntity.class));
141141
}
142142

143143
protected InternalRequest updateUserRequest(final String dbName, final String user, final UserUpdateOptions options) {
@@ -173,10 +173,10 @@ protected InternalRequest executeRequest(final Request<?> request) {
173173
}
174174

175175
protected <T> ResponseDeserializer<Response<T>> responseDeserializer(Class<T> type) {
176-
return (response, ctx) -> new Response<>(
176+
return (response) -> new Response<>(
177177
response.getResponseCode(),
178178
response.getMeta(),
179-
getSerde().deserializeUserData(response.getBody(), type, ctx)
179+
getSerde().deserializeUserData(response.getBody(), type)
180180
);
181181
}
182182

0 commit comments

Comments
 (0)