You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by re...@apache.org on 2026/08/17 17:58:45 UTC

(sling-org-apache-sling-resourceresolver) branch SLING-13284-x created (now 351b6a7b)

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

reschke pushed a change to branch SLING-13284-x
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git


      at 351b6a7b SLING-13284 - Do not abort alias/vanity cache init on out-of-order qu… (#225)

This branch includes the following new commits:

     new 351b6a7b SLING-13284 - Do not abort alias/vanity cache init on out-of-order qu… (#225)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(sling-org-apache-sling-resourceresolver) 01/01: SLING-13284 - Do not abort alias/vanity cache init on out-of-order qu… (#225)

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reschke pushed a commit to branch SLING-13284-x
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourceresolver.git

commit 351b6a7b8f50d9461ecd63b57f9a29dac7e5a90d
Author: Sagar Miglani <85...@users.noreply.github.com>
AuthorDate: Tue Aug 4 15:22:47 2026 +0530

    SLING-13284 - Do not abort alias/vanity cache init on out-of-order qu… (#225)
    
    * SLING-13284 - Do not abort alias/vanity cache init on out-of-order query results
    
    Demote the ordering checks in PagedQueryIterator from fatal throws to
    log.warn. The checks compared live property values against an async
    index sort order, which can lag after a property write.
    
    * SLING-13284 - Remove unused QueryImplementationException
---
 .../impl/mapping/PagedQueryIterator.java           | 33 ++++++------
 .../impl/mapping/PagedQueryIteratorTest.java       | 58 ++++++++++++++++++----
 2 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIterator.java b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIterator.java
index 40356f06..2081daa9 100644
--- a/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIterator.java
+++ b/src/main/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIterator.java
@@ -90,18 +90,22 @@ public class PagedQueryIterator implements Iterator<Resource> {
         if (values.length > 0) {
             String value = values[0];
             if (value.compareTo(lastKey) < 0) {
-                String message = String.format(
-                        "unexpected query result in page %d, property name '%s', got '%s', despite querying for > '%s'",
-                        (page - 1), propertyName, value, lastKey);
-                log.error(message);
-                throw new QueryImplementationException(message);
+                log.warn(
+                        "unexpected query result in page {}, property name '{}', got '{}', despite querying for > '{}'"
+                                + " (the async index may not yet reflect the current property value)",
+                        (page - 1),
+                        propertyName,
+                        value,
+                        lastKey);
             }
             if (lastValue != null && value.compareTo(lastValue) < 0) {
-                String message = String.format(
-                        "unexpected query result in page %d, property name '%s', got '%s', last value was '%s'",
-                        (page - 1), propertyName, value, lastValue);
-                log.error(message);
-                throw new QueryImplementationException(message);
+                log.warn(
+                        "unexpected query result in page {}, property name '{}', got '{}', last value was '{}'"
+                                + " (the async index may not yet reflect the current property value)",
+                        (page - 1),
+                        propertyName,
+                        value,
+                        lastValue);
             }
 
             // keep information about large key counts
@@ -178,13 +182,4 @@ public class PagedQueryIterator implements Iterator<Resource> {
             return "";
         }
     }
-
-    /**
-     * Thrown when the underlying repository misbehaves with respect to sorting on multivalued properties.
-     */
-    public static class QueryImplementationException extends RuntimeException {
-        public QueryImplementationException(String message) {
-            super(message);
-        }
-    }
 }
diff --git a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIteratorTest.java b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIteratorTest.java
index 61e1cc5e..24ac0777 100644
--- a/src/test/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIteratorTest.java
+++ b/src/test/java/org/apache/sling/resourceresolver/impl/mapping/PagedQueryIteratorTest.java
@@ -86,31 +86,71 @@ public class PagedQueryIteratorTest extends AbstractMappingMapEntriesTest {
         assertEquals("", it.getWarning());
     }
 
-    @Test(expected = PagedQueryIterator.QueryImplementationException.class)
+    @Test
     public void testSimpleWrongOrder() {
+        // SLING-13284: out-of-order results (from a stale async index) should not abort iteration
         String[] expected = new String[] {"a", "b", "d", "c"};
         Collection<Resource> expectedResources = toResourceList(expected);
         when(resourceResolver.findResources(eq("testSimpleWrongOrder"), eq("JCR-SQL2")))
                 .thenReturn(expectedResources.iterator());
-        // incorrect sort order within a query page
-        Iterator<Resource> it =
+        PagedQueryIterator it =
                 new PagedQueryIterator("alias", PROPNAME, resourceResolver, "testSimpleWrongOrder", 2000);
-        while (it.hasNext()) {
-            it.next();
-        }
+        checkResult(it, expected);
     }
 
-    @Test(expected = PagedQueryIterator.QueryImplementationException.class)
+    @Test
     public void testSimpleWrongResultAfterKey() {
+        // SLING-13284: out-of-order results across page boundaries should not abort iteration
         String[] expected = new String[] {"x", "x", "a", "a"};
         Collection<Resource> expectedResources = toResourceList(expected);
         when(resourceResolver.findResources("testSimpleWrongOrder", "JCR-SQL2"))
                 .thenReturn(expectedResources.iterator());
-        // incorrect return value based on previous key
-        Iterator<Resource> it = new PagedQueryIterator("alias", PROPNAME, resourceResolver, "testSimpleWrongOrder", 1);
+        PagedQueryIterator it = new PagedQueryIterator("alias", PROPNAME, resourceResolver, "testSimpleWrongOrder", 1);
+        int count = 0;
+        while (it.hasNext()) {
+            it.next();
+            count++;
+        }
+        assertEquals(3, count);
+    }
+
+    @Test
+    public void testWrongResultBelowPageBoundary() {
+        // SLING-13284: a result on a new page has a value below the page boundary key.
+        // Page 1: ["b", "c"] with pageSize=1 — "c" triggers page break (lastKey="c").
+        // Page 2: returns "a" which is < lastKey "c" — must not abort.
+        Collection<Resource> page1 = toResourceList("b", "c");
+        Collection<Resource> page2 = toResourceList("a");
+        when(resourceResolver.findResources("boundary ''", "JCR-SQL2")).thenReturn(page1.iterator());
+        when(resourceResolver.findResources("boundary 'c'", "JCR-SQL2")).thenReturn(page2.iterator());
+
+        PagedQueryIterator it = new PagedQueryIterator("alias", PROPNAME, resourceResolver, "boundary '%s'", 1);
+        int count = 0;
+        while (it.hasNext()) {
+            it.next();
+            count++;
+        }
+        assertEquals(2, count);
+    }
+
+    @Test
+    public void testStaleAsyncIndexDoesNotAbortIteration() {
+        // SLING-13284: Reproduces the scenario where an async index delivers rows in an order
+        // that no longer matches the live property values (e.g. sling:alias was rewritten
+        // between the last index cycle and a restart). All rows must still be processed.
+        // The descending order simulates what happens when the index sorts by a stale
+        // first([sling:alias]) value that no longer matches the current values[0].
+        String[] staleOrder = new String[] {"ayacucho-fleeces", "ayacucho-bamboo", "ayacucho"};
+        Collection<Resource> resources = toResourceList(staleOrder);
+        when(resourceResolver.findResources("staleIndex", "JCR-SQL2")).thenReturn(resources.iterator());
+
+        PagedQueryIterator it = new PagedQueryIterator("alias", PROPNAME, resourceResolver, "staleIndex", 2000);
+        int count = 0;
         while (it.hasNext()) {
             it.next();
+            count++;
         }
+        assertEquals("all rows must be processed even when order doesn't match", 3, count);
     }
 
     @Test