void-ptr974 commented on code in PR #26148:
URL: https://github.com/apache/pulsar/pull/26148#discussion_r3566299726


##########
pulsar-metadata/src/main/java/org/apache/pulsar/metadata/impl/oxia/OxiaMetadataStore.java:
##########
@@ -277,8 +277,9 @@ protected CompletableFuture<Void> storeScanByIndex(
                     // (it's the scan-and-filter compat-path predicate).
                     CompletableFuture<Void> chain = 
CompletableFuture.completedFuture(null);
                     for (String key : primaryKeys) {
+                        Set<Option> getOpts = 
OptionsHelper.withResolvedPartitionKey(opts, key);
                         chain = chain
-                                .thenCompose(__ -> storeGet(key, opts))
+                                .thenCompose(__ -> storeGet(key, getOpts))

Review Comment:
   Fixed. The partition-key resolution now happens inside the sequential 
`thenCompose`, so the resolver for the next primary key is not evaluated until 
the preceding `storeGet` has completed.
   
   Added a regression test that holds the first read pending and makes the 
second resolver fail. It verifies that the scan remains pending before the 
first read completes, then observes `onNext` followed by `onError`, with no 
read for the second key.



##########
pulsar-metadata/src/main/java/org/apache/pulsar/metadata/api/OptionsHelper.java:
##########
@@ -55,6 +56,32 @@ public static String partitionKey(Set<Option> opts) {
         return null;
     }
 
+    /**
+     * Return {@code opts} with a concrete {@link Option.PartitionKey} added 
when a
+     * {@link Option.PartitionKeyResolver} can derive one from {@code path}. 
Existing fixed
+     * partition keys are preserved.
+     */
+    public static Set<Option> withResolvedPartitionKey(Set<Option> opts, 
String path) {
+        if (opts == null || opts.isEmpty()) {
+            return Set.of();
+        }
+        if (partitionKey(opts) != null) {
+            return opts;
+        }
+        for (Option o : opts) {
+            if (o instanceof Option.PartitionKeyResolver resolver) {
+                String partitionKey = resolver.resolver().apply(path);

Review Comment:
   Fixed. `PartitionKeyResolver` now requires a non-null key for every scanned 
primary path. Returning `null` fails the scan with an `IllegalStateException` 
instead of falling back to an unpartitioned read, preventing a silent 
cross-shard miss.
   
   Added a test that verifies the error callback and confirms that no primary 
read is issued when the resolver cannot provide a key.



##########
pulsar-metadata/src/test/java/org/apache/pulsar/metadata/OxiaPartitionKeyTest.java:
##########
@@ -114,4 +118,45 @@ public void getChildrenWithPartitionKey() throws Exception 
{
         assertTrue(children.containsAll(List.of("a", "b")),
                 "expected children a and b, got: " + children);
     }
+
+    @Test
+    public void scanByIndexUsesPartitionKeyResolverForPrimaryReads() throws 
Exception {
+        @Cleanup
+        MetadataStore store = newStore();
+
+        String parent = "/partition-key-index-scan-" + System.nanoTime();
+        String indexName = "idx:partition-key-resolver-" + System.nanoTime();
+        String indexKey = "match";
+        RoutedKey routedKey = 
createIndexedKeyOnlyVisibleWithPartitionKey(store, parent, indexName, indexKey);

Review Comment:
   Updated. The integration test now retains two cross-shard indexed records 
with distinct partition keys and asserts that both primary paths are returned 
by the scan. This exercises per-result resolution rather than a single 
scan-level routing key.
   
   The focused unit and multi-shard Oxia integration tests pass.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to