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

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

commit 268c5dddee737f1a72ad59fa8e6444bcf66e040b
Author: Sagar Miglani <[email protected]>
AuthorDate: Fri Jul 31 17:00:13 2026 +0530

    SLING-13284 - Do not abort alias/vanity cache init on out-of-order query 
results
    
    The ordering check in PagedQueryIterator compared live property values
    (read from the repository) against the sort order delivered by an async
    Lucene index. Since async indexes are eventually consistent, their sort
    order can lag behind the current repository state after a property write.
    The previous behavior treated this lag as a fatal error and aborted the
    entire alias/vanity cache build, leaving alias resolution non-functional
    until a manual reindex + restart.
    
    Demote the two throws to log.warn and continue processing. The row
    contains a valid alias/vanity value that should be cached regardless of
    sort position. This also addresses the vanity-path variant (SLING-13248).
---
 .../impl/mapping/PagedQueryIterator.java           | 24 +++++++------
 .../impl/mapping/PagedQueryIteratorTest.java       | 42 +++++++++++++++++-----
 2 files changed, 47 insertions(+), 19 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..8a1239b0 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
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..7af9b43d 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,55 @@ 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);
+        while (it.hasNext()) {
+            it.next();
+        }
+    }
+
+    @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.
+        String[] indexOrder = new String[] {"ayacucho", "ayacucho-bamboo", 
"ayacucho-fleeces"};
+        Collection<Resource> resources = toResourceList(indexOrder);
+        when(resourceResolver.findResources(eq("staleIndex"), 
eq("JCR-SQL2"))).thenReturn(resources.iterator());
+
+        // Simulate: index thinks order is ayacucho < ayacucho-bamboo < 
ayacucho-fleeces
+        // but the live values on the second node changed from 
"ayacucho-bamboo" to "aaa"
+        // (the index hasn't caught up). We model this by having the values 
already in the
+        // "wrong" order from the iterator's perspective: row 2 < row 1.
+        String[] staleOrder = new String[] {"ayacucho-fleeces", 
"ayacucho-bamboo", "ayacucho"};
+        Collection<Resource> staleResources = toResourceList(staleOrder);
+        when(resourceResolver.findResources(eq("staleIndex"), 
eq("JCR-SQL2"))).thenReturn(staleResources.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

Reply via email to