From 9e620174e43be89b89a37a7fad0917781bceed7e Mon Sep 17 00:00:00 2001 From: Michele Rastelli Date: Tue, 25 Apr 2023 11:59:15 +0200 Subject: [PATCH] Index cache refilling (DE-564) --- .../internal/InternalArangoCollection.java | 9 ++ .../arangodb/model/DocumentCreateOptions.java | 14 +++ .../arangodb/model/DocumentDeleteOptions.java | 16 ++++ .../model/DocumentReplaceOptions.java | 15 ++++ .../arangodb/model/DocumentUpdateOptions.java | 16 ++++ .../com/arangodb/ArangoCollectionTest.java | 90 +++++++++++++++++++ 6 files changed, 160 insertions(+) diff --git a/src/main/java/com/arangodb/internal/InternalArangoCollection.java b/src/main/java/com/arangodb/internal/InternalArangoCollection.java index fdfdbc24e..629d8bc3c 100644 --- a/src/main/java/com/arangodb/internal/InternalArangoCollection.java +++ b/src/main/java/com/arangodb/internal/InternalArangoCollection.java @@ -52,6 +52,7 @@ public abstract class InternalArangoCollection, D private static final String PATH_API_USER = "/_api/user"; private static final String MERGE_OBJECTS = "mergeObjects"; + private static final String REFILL_INDEX_CACHES = "refillIndexCaches"; private static final String IGNORE_REVS = "ignoreRevs"; private static final String RETURN_NEW = "returnNew"; private static final String NEW = "new"; @@ -90,6 +91,7 @@ protected Request insertDocumentRequest(final T value, final DocumentCreateO request.putQueryParam(OVERWRITE, params.getOverwrite()); request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.setBody(util(Serializer.CUSTOM).serialize(value)); @@ -130,6 +132,7 @@ protected Request insertDocumentsRequest(final Collection values, final D request.putQueryParam(OVERWRITE, params.getOverwrite()); request.putQueryParam(OVERWRITE_MODE, params.getOverwriteMode() != null ? params.getOverwriteMode().getValue() : null); request.putQueryParam(MERGE_OBJECTS, params.getMergeObjects()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); request.putHeaderParam(TRANSACTION_ID, params.getStreamTransactionId()); request.setBody(util(Serializer.CUSTOM) @@ -266,6 +269,7 @@ protected Request replaceDocumentRequest( request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); request.setBody(util(Serializer.CUSTOM).serialize(value)); return request; } @@ -301,6 +305,7 @@ protected Request replaceDocumentsRequest(final Collection values, final request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); request.setBody(util(Serializer.CUSTOM) .serialize(values, new ArangoSerializer.Options().serializeNullValues(false).stringAsJson(true))); return request; @@ -363,6 +368,7 @@ protected Request updateDocumentRequest(final String key, final T value, fin request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); request.setBody(util(Serializer.CUSTOM).serialize(value, new ArangoSerializer.Options() .serializeNullValues(params.getSerializeNull() == null || params.getSerializeNull()))); return request; @@ -402,6 +408,7 @@ protected Request updateDocumentsRequest(final Collection values, final D request.putQueryParam(RETURN_NEW, params.getReturnNew()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); request.setBody(util(Serializer.CUSTOM).serialize(values, new ArangoSerializer.Options() .serializeNullValues(params.getSerializeNull() == null || params.getSerializeNull()) .stringAsJson(true))); @@ -455,6 +462,7 @@ protected Request deleteDocumentRequest(final String key, final DocumentDeleteOp request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); return request; } @@ -478,6 +486,7 @@ protected Request deleteDocumentsRequest(final Collection keys, final Doc request.putQueryParam(ArangoRequestParam.WAIT_FOR_SYNC, params.getWaitForSync()); request.putQueryParam(RETURN_OLD, params.getReturnOld()); request.putQueryParam(SILENT, params.getSilent()); + request.putQueryParam(REFILL_INDEX_CACHES, params.getRefillIndexCaches()); request.setBody(util().serialize(keys)); return request; } diff --git a/src/main/java/com/arangodb/model/DocumentCreateOptions.java b/src/main/java/com/arangodb/model/DocumentCreateOptions.java index 3c8a52337..691d2d3fb 100644 --- a/src/main/java/com/arangodb/model/DocumentCreateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentCreateOptions.java @@ -36,6 +36,7 @@ public class DocumentCreateOptions { private Boolean silent; private String streamTransactionId; private Boolean mergeObjects; + private Boolean refillIndexCaches; public DocumentCreateOptions() { @@ -168,4 +169,17 @@ public DocumentCreateOptions mergeObjects(Boolean mergeObjects) { return this; } + public Boolean getRefillIndexCaches() { + return refillIndexCaches; + } + + /** + * @param refillIndexCaches Whether to add a new entry to the in-memory edge cache if an edge document is inserted. + * @return options + * @since ArangoDB 3.11 + */ + public DocumentCreateOptions refillIndexCaches(Boolean refillIndexCaches) { + this.refillIndexCaches = refillIndexCaches; + return this; + } } diff --git a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java b/src/main/java/com/arangodb/model/DocumentDeleteOptions.java index e0e566952..c187db435 100644 --- a/src/main/java/com/arangodb/model/DocumentDeleteOptions.java +++ b/src/main/java/com/arangodb/model/DocumentDeleteOptions.java @@ -33,6 +33,7 @@ public class DocumentDeleteOptions { private Boolean returnOld; private Boolean silent; private String streamTransactionId; + private Boolean refillIndexCaches; public DocumentDeleteOptions() { super(); @@ -106,4 +107,19 @@ public DocumentDeleteOptions streamTransactionId(final String streamTransactionI return this; } + public Boolean getRefillIndexCaches() { + return refillIndexCaches; + } + + /** + * @param refillIndexCaches Whether to delete an existing entry from the in-memory edge cache and refill it with + * another edge if an edge document is removed. + * @return options + * @since ArangoDB 3.11 + */ + public DocumentDeleteOptions refillIndexCaches(Boolean refillIndexCaches) { + this.refillIndexCaches = refillIndexCaches; + return this; + } + } diff --git a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java index 2646f847d..4847964f3 100644 --- a/src/main/java/com/arangodb/model/DocumentReplaceOptions.java +++ b/src/main/java/com/arangodb/model/DocumentReplaceOptions.java @@ -35,6 +35,7 @@ public class DocumentReplaceOptions { private Boolean returnOld; private Boolean silent; private String streamTransactionId; + private Boolean refillIndexCaches; public DocumentReplaceOptions() { super(); @@ -136,4 +137,18 @@ public DocumentReplaceOptions streamTransactionId(final String streamTransaction return this; } + public Boolean getRefillIndexCaches() { + return refillIndexCaches; + } + + /** + * @param refillIndexCaches Whether to update an existing entry in the in-memory edge cache if an edge document is + * replaced. + * @return options + * @since ArangoDB 3.11 + */ + public DocumentReplaceOptions refillIndexCaches(Boolean refillIndexCaches) { + this.refillIndexCaches = refillIndexCaches; + return this; + } } diff --git a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java index 20d7b8cca..e16781f17 100644 --- a/src/main/java/com/arangodb/model/DocumentUpdateOptions.java +++ b/src/main/java/com/arangodb/model/DocumentUpdateOptions.java @@ -38,6 +38,7 @@ public class DocumentUpdateOptions { private Boolean serializeNull; private Boolean silent; private String streamTransactionId; + private Boolean refillIndexCaches; public DocumentUpdateOptions() { super(); @@ -185,4 +186,19 @@ public DocumentUpdateOptions streamTransactionId(final String streamTransactionI return this; } + public Boolean getRefillIndexCaches() { + return refillIndexCaches; + } + + /** + * @param refillIndexCaches Whether to update an existing entry in the in-memory edge cache if an edge document is + * updated. + * @return options + * @since ArangoDB 3.11 + */ + public DocumentUpdateOptions refillIndexCaches(Boolean refillIndexCaches) { + this.refillIndexCaches = refillIndexCaches; + return this; + } + } diff --git a/src/test/java/com/arangodb/ArangoCollectionTest.java b/src/test/java/com/arangodb/ArangoCollectionTest.java index 66067edb6..ca67472ee 100644 --- a/src/test/java/com/arangodb/ArangoCollectionTest.java +++ b/src/test/java/com/arangodb/ArangoCollectionTest.java @@ -276,6 +276,18 @@ void insertDocumentWaitForSync(ArangoCollection collection) { assertThat(doc.getNew()).isNull(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentRefillIndexCaches(ArangoCollection collection) { + final DocumentCreateOptions options = new DocumentCreateOptions().refillIndexCaches(true); + final DocumentCreateEntity doc = collection.insertDocument(new BaseDocument(), options); + assertThat(doc).isNotNull(); + assertThat(doc.getId()).isNotNull(); + assertThat(doc.getKey()).isNotNull(); + assertThat(doc.getRev()).isNotNull(); + assertThat(doc.getNew()).isNull(); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void insertDocumentAsJson(ArangoCollection collection) { @@ -327,6 +339,15 @@ void insertDocumentsSilent(ArangoCollection collection) { assertThat(info.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void insertDocumentsRefillIndexCaches(ArangoCollection collection) { + final MultiDocumentEntity> info = + collection.insertDocuments(Arrays.asList(new BaseDocument(), new BaseDocument()), + new DocumentCreateOptions().refillIndexCaches(true)); + assertThat(info.getErrors()).isEmpty(); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void getDocument(ArangoCollection collection) { @@ -922,6 +943,29 @@ void updateDocumentPreconditionFailed(ArangoCollection collection) { assertThat(readDocument.getAttribute("foo")).isEqualTo("b"); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentRefillIndexCaches(ArangoCollection collection) { + BaseDocument doc = new BaseDocument(); + DocumentCreateEntity createResult = collection.insertDocument(doc); + doc.addAttribute("foo", "bar"); + DocumentUpdateEntity updateResult = collection.updateDocument(createResult.getKey(), + doc , new DocumentUpdateOptions().refillIndexCaches(true)); + assertThat(updateResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void updateDocumentsRefillIndexCaches(ArangoCollection collection) { + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = + collection.updateDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentUpdateOptions().refillIndexCaches(true), BaseDocument.class); + assertThat(info.getErrors()).isEmpty(); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void replaceDocument(ArangoCollection collection) { @@ -1108,6 +1152,28 @@ void replaceDocumentsSilent(ArangoCollection collection) { assertThat(info.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentRefillIndexCaches(ArangoCollection collection) { + final BaseDocument doc = new BaseDocument(UUID.randomUUID().toString()); + final DocumentCreateEntity createResult = collection.insertDocument(doc); + final DocumentUpdateEntity replaceResult = collection.replaceDocument(createResult.getKey(), doc, + new DocumentReplaceOptions().refillIndexCaches(true)); + assertThat(replaceResult.getRev()) + .isNotNull() + .isNotEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void replaceDocumentsRefillIndexCaches(ArangoCollection collection) { + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = + collection.replaceDocuments(Collections.singletonList(new BaseDocument(createResult.getKey())), + new DocumentReplaceOptions().refillIndexCaches(true)); + assertThat(info.getErrors()).isEmpty(); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void deleteDocument(ArangoCollection collection) { @@ -1189,6 +1255,30 @@ void deleteDocumentsSilent(ArangoCollection collection) { assertThat(info.getErrors()).isEmpty(); } + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentRefillIndexCaches(ArangoCollection collection) { + DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + DocumentDeleteEntity deleteResult = collection.deleteDocument(createResult.getKey(), + BaseDocument.class, + new DocumentDeleteOptions().refillIndexCaches(true)); + assertThat(deleteResult.getRev()) + .isNotNull() + .isEqualTo(createResult.getRev()); + } + + @ParameterizedTest(name = "{index}") + @MethodSource("cols") + void deleteDocumentsRefillIndexCaches(ArangoCollection collection) { + assumeTrue(isSingleServer()); + final DocumentCreateEntity createResult = collection.insertDocument(new BaseDocument()); + final MultiDocumentEntity> info = collection.deleteDocuments( + Collections.singletonList(createResult.getKey()), + BaseDocument.class, + new DocumentDeleteOptions().refillIndexCaches(true)); + assertThat(info.getErrors()).isEmpty(); + } + @ParameterizedTest(name = "{index}") @MethodSource("cols") void getIndex(ArangoCollection collection) {