This is an automated email from the ASF dual-hosted git repository.

reschke pushed a commit to branch OAK-10650
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit 870cc5550110c2267826af3d9e361fadc3eb605e
Author: Julian Reschke <[email protected]>
AuthorDate: Wed Feb 14 13:55:00 2024 +0100

    OAK-10650: MongoDocumentStore.findDocuments can fail with BSON exception
---
 .../plugins/document/mongo/MongoDocumentStore.java | 52 +++++++++++++++++++---
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
index 1f156f4100..604829b38d 100644
--- 
a/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
+++ 
b/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
@@ -84,6 +84,7 @@ import 
org.apache.jackrabbit.oak.plugins.document.locks.StripedNodeDocumentLocks
 import org.apache.jackrabbit.oak.plugins.document.util.Utils;
 import org.apache.jackrabbit.oak.stats.Clock;
 import org.apache.jackrabbit.oak.commons.PerfLogger;
+import org.bson.BSONException;
 import org.bson.BsonMaximumSizeExceededException;
 import org.bson.conversions.Bson;
 import org.jetbrains.annotations.NotNull;
@@ -1524,12 +1525,48 @@ public class MongoDocumentStore implements 
DocumentStore {
     }
 
     private <T extends Document> Map<String, T> findDocuments(Collection<T> 
collection, Set<String> keys) {
-        Map<String, T> docs = new HashMap<String, T>();
-        if (!keys.isEmpty()) {
-            List<Bson> conditions = new ArrayList<>(keys.size());
-            for (String key : keys) {
-                conditions.add(getByKeyQuery(key));
+        try {
+            Map<String, T> docs = new HashMap<String, T>();
+            if (!keys.isEmpty()) {
+                List<Bson> conditions = new ArrayList<>(keys.size());
+                for (String key : keys) {
+                    conditions.add(getByKeyQuery(key));
+                }
+                MongoCollection<BasicDBObject> dbCollection;
+                if (secondariesWithinAcceptableLag()) {
+                    dbCollection = getDBCollection(collection);
+                } else {
+                    lagTooHigh();
+                    dbCollection = 
getDBCollection(collection).withReadPreference(ReadPreference.primary());
+                }
+                execute(session -> {
+                    FindIterable<BasicDBObject> cursor;
+                    if (session != null) {
+                        cursor = dbCollection.find(session, 
Filters.or(conditions));
+                    } else {
+                        cursor = dbCollection.find(Filters.or(conditions));
+                    }
+                    for (BasicDBObject doc : cursor) {
+                        T foundDoc = convertFromDBObject(collection, doc);
+                        docs.put(foundDoc.getId(), foundDoc);
+                    }
+                    return null;
+                }, collection);
             }
+            return docs;
+        } catch (BSONException ex) {
+            // TODO: refactor, see OAK-10650
+            LOG.error("trying bulk find, retrying one-by-one", ex);
+            return findDocumentsOneByOne(collection, keys);
+        }
+    }
+
+    // variant of findDocuments that avoids BSON exception by iterating 
instead of doing a bulk operation
+    private <T extends Document> Map<String, T> 
findDocumentsOneByOne(Collection<T> collection, Set<String> keys) {
+        Map<String, T> docs = new HashMap<String, T>();
+        for (String key : keys) {
+            Bson condition = getByKeyQuery(key);
+
             MongoCollection<BasicDBObject> dbCollection;
             if (secondariesWithinAcceptableLag()) {
                 dbCollection = getDBCollection(collection);
@@ -1540,9 +1577,9 @@ public class MongoDocumentStore implements DocumentStore {
             execute(session -> {
                 FindIterable<BasicDBObject> cursor;
                 if (session != null) {
-                    cursor = dbCollection.find(session, 
Filters.or(conditions));
+                    cursor = dbCollection.find(session, condition);
                 } else {
-                    cursor = dbCollection.find(Filters.or(conditions));
+                    cursor = dbCollection.find(condition);
                 }
                 for (BasicDBObject doc : cursor) {
                     T foundDoc = convertFromDBObject(collection, doc);
@@ -1551,6 +1588,7 @@ public class MongoDocumentStore implements DocumentStore {
                 return null;
             }, collection);
         }
+
         return docs;
     }
 

Reply via email to