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

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


The following commit(s) were added to refs/heads/1.22 by this push:
     new 503569c43a OAK-10127: Log warn message when MongoDB document is big 
(backport to 1.22) (#2748)
503569c43a is described below

commit 503569c43a4eb352d17908b8f7f62202cc6f890c
Author: Julian Reschke <[email protected]>
AuthorDate: Fri Feb 20 10:11:09 2026 +0100

    OAK-10127: Log warn message when MongoDB document is big (backport to 1.22) 
(#2748)
---
 .../plugins/document/mongo/MongoDocumentStore.java |  21 +++
 .../document/mongo/MongoDBExceptionTest.java       | 142 +++++++++++++++++++++
 2 files changed, 163 insertions(+)

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 2ea202891d..4b42d3f53b 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
@@ -45,6 +45,9 @@ import 
com.google.common.util.concurrent.UncheckedExecutionException;
 import com.mongodb.Block;
 import com.mongodb.DBObject;
 import com.mongodb.MongoBulkWriteException;
+import com.mongodb.MongoWriteException;
+import com.mongodb.MongoCommandException;
+import com.mongodb.WriteError;
 import com.mongodb.MongoClient;
 import com.mongodb.MongoClientURI;
 import com.mongodb.ReadPreference;
@@ -74,6 +77,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.BsonMaximumSizeExceededException;
 import org.bson.conversions.Bson;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -1009,6 +1013,15 @@ public class MongoDocumentStore implements DocumentStore 
{
                 }
             }
             return oldDoc;
+        } catch (MongoWriteException e) {
+            WriteError werr = e.getError();
+            LOG.error("Failed to update the document with Id={} with 
MongoWriteException message = '{}'.",
+                    updateOp.getId(), werr.getMessage());
+            throw handleException(e, collection, updateOp.getId());
+        } catch (MongoCommandException e) {
+            LOG.error("Failed to update the document with Id={} with 
MongoCommandException message ='{}'. ",
+                    updateOp.getId(), e.getMessage());
+            throw handleException(e, collection, updateOp.getId());
         } catch (Exception e) {
             throw handleException(e, collection, updateOp.getId());
         } finally {
@@ -1364,6 +1377,14 @@ public class MongoDocumentStore implements DocumentStore 
{
                 }
                 insertSuccess = true;
                 return true;
+            } catch (BsonMaximumSizeExceededException e) {
+                for (T doc : docs) {
+                    LOG.error("Failed to create one of the documents " +
+                                    "with BsonMaximumSizeExceededException 
message = '{}'. " +
+                                    "The document id={} has estimated size={} 
in VM.",
+                                    e.getMessage(), doc.getId(), 
doc.getMemory());
+                }
+                return false;
             } catch (MongoException e) {
                 LOG.warn("Encountered MongoException while inserting 
documents: {} - exception: {}",
                         ids, e.getMessage());
diff --git 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDBExceptionTest.java
 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDBExceptionTest.java
index 73a1d9d49d..7fa9766c35 100644
--- 
a/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDBExceptionTest.java
+++ 
b/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDBExceptionTest.java
@@ -25,17 +25,23 @@ import org.apache.jackrabbit.oak.plugins.document.Path;
 import org.apache.jackrabbit.oak.plugins.document.Revision;
 import org.apache.jackrabbit.oak.plugins.document.UpdateOp;
 import org.apache.jackrabbit.oak.plugins.document.util.Utils;
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
 import org.junit.After;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
 import static java.util.Collections.singletonList;
 import static org.hamcrest.Matchers.containsString;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.junit.Assert.assertFalse;
 
 public class MongoDBExceptionTest {
 
@@ -132,8 +138,144 @@ public class MongoDBExceptionTest {
         }
     }
 
+    @Test
+    public void createOrUpdate16MBDoc() {
+        LogCustomizer customizer = 
LogCustomizer.forLogger(MongoDocumentStore.class.getName()).create();
+        customizer.starting();
+        String id = "/foo";
+        UpdateOp updateOp = new UpdateOp(id, true);
+        updateOp = create16MBProp(updateOp);
+        exceptionMsg = "Document to upsert is larger than 16777216";
+        try {
+            store.createOrUpdate(Collection.NODES, updateOp);
+            fail("DocumentStoreException expected");
+        } catch (DocumentStoreException e) {
+            assertThat(e.getMessage(), containsString(exceptionMsg));
+            String log = customizer.getLogs().toString();
+            assertTrue("Message doesn't contain the id", log.contains(id));
+        }
+        customizer.finished();
+    }
+
+    @Test
+    public void update16MBDoc() {
+
+        String docName = "/foo";
+        UpdateOp updateOp = new UpdateOp(docName, true);
+        updateOp = create1MBProp(updateOp);
+        store.createOrUpdate(Collection.NODES, updateOp);
+        updateOp = create16MBProp(updateOp);
+        exceptionMsg = "Resulting document after update is larger than 
16777216";
+        try {
+            store.createOrUpdate(Collection.NODES, updateOp);
+            fail("DocumentStoreException expected");
+        } catch (DocumentStoreException e) {
+            assertThat(e.getMessage(), containsString(exceptionMsg));
+            assertThat(e.getMessage(), containsString(docName));
+        }
+    }
+
+    @Test
+    public void multiCreateOrUpdate16MBDoc() {
+
+        List<UpdateOp> updateOps = new ArrayList<>();
+        LogCustomizer customizer = 
LogCustomizer.forLogger(MongoDocumentStore.class.getName()).create();
+        customizer.starting();
+        String id1 = "/test";
+        String id2 = "/foo";
+
+        UpdateOp op = new UpdateOp(id1, true);
+        op = create1MBProp(op);
+
+        store.createOrUpdate(Collection.NODES, op);
+
+        UpdateOp op1 = new UpdateOp(id2, true);
+        op1 = create16MBProp(op1);
+
+        // Updating both doc with 16MB
+        op = create16MBProp(op);
+        updateOps.add(op);
+        updateOps.add(op1);
+        exceptionMsg = "Resulting document after update is larger than 
16777216";
+
+        try {
+            store.createOrUpdate(Collection.NODES, updateOps);
+            fail("DocumentStoreException expected");
+        } catch (DocumentStoreException e) {
+            assertThat(e.getMessage(), containsString(exceptionMsg));
+            String log = customizer.getLogs().toString();
+            assertTrue("Message doesn't contain the id", log.contains(id1));
+        }
+        customizer.finished();
+    }
+
+    @Test
+    public void create16MBDoc() {
+
+        List<UpdateOp> updateOps = new ArrayList<>();
+        LogCustomizer customizer = 
LogCustomizer.forLogger(MongoDocumentStore.class.getName()).create();
+        customizer.starting();
+        String id1 = "/test";
+        String id2 = "/foo";
+        UpdateOp op1 = new UpdateOp(id1, true);
+        op1 = create1MBProp(op1);
+
+        UpdateOp op2 = new UpdateOp(id2, false);
+        op2 = create1MBProp(op2);
+        op2 = create16MBProp(op2);
+
+        updateOps.add(op1);
+        updateOps.add(op2);
+        assertFalse(store.create(Collection.NODES, updateOps));
+        String log = customizer.getLogs().toString();
+        assertTrue("Message doesn't contain the id", log.contains(id2));
+    }
+
+    @Test
+    public void findAndUpdate16MBDoc() throws Exception {
+        String id = "/foo";
+        UpdateOp op = new UpdateOp(id, true);
+        op = create1MBProp(op);
+        store.createOrUpdate(Collection.NODES, op);
+        op = create16MBProp(op);
+        exceptionMsg = "Resulting document after update is larger than 
16777216";
+        try {
+            store.findAndUpdate(Collection.NODES, op);
+            fail("DocumentStoreException expected");
+        } catch (DocumentStoreException e) {
+            assertThat(e.getMessage(), containsString(exceptionMsg));
+            assertThat(e.getMessage(), containsString(id));
+       }
+    }
+
     private void setExceptionMsg() {
         client.setExceptionBeforeUpdate(exceptionMsg);
         client.setExceptionBeforeQuery(exceptionMsg);
     }
+
+    private UpdateOp create1MBProp(UpdateOp op) {
+        // create a 1 MB property
+        String content = create1MBContent();
+        op.set("property0", content);
+        return op;
+    }
+
+    private UpdateOp create16MBProp(UpdateOp op) {
+        // create a 1 MB property
+        String content = create1MBContent();
+
+        //create 16MB property
+        for (int i = 0; i < 16; i++) {
+            op.set("property"+ i, content);
+        }
+        return op;
+    }
+
+    private String create1MBContent() {
+        char[] chars = new char[1024 * 1024];
+        Arrays.fill(chars, '0');
+        String content = new String(chars);
+        return content;
+    }
 }
+

Reply via email to