mjsax commented on code in PR #22570:
URL: https://github.com/apache/kafka/pull/22570#discussion_r3592266977


##########
streams/src/main/java/org/apache/kafka/streams/KafkaStreams.java:
##########
@@ -1780,38 +1782,70 @@ public Collection<StreamsMetadata> 
streamsMetadataForStore(final String storeNam
         return streamsMetadataState.allMetadataForStore(storeName);
     }
 
+    /**
+     * Finds the metadata containing the active hosts and standby hosts where 
the key being queried would reside,
+     * without requiring record headers to be provided.
+     * <p>
+     * If your partitioner or serializer makes use of headers, use the Headers 
overload, otherwise the returned metadata may not match where the key actually 
resides.

Review Comment:
   ```suggestion
        * If your partitioner or serializer makes use of headers, use the 
{@link #queryMetadataForKey(String, Object, Headers, Serializer) Headers} 
overload, otherwise the returned metadata may not match where the key actually 
resides.
   ```



##########
streams/src/main/java/org/apache/kafka/streams/kstream/internals/KTableImpl.java:
##########
@@ -1438,4 +1436,78 @@ private static void maybeSetOutputVersioned(final 
GraphNode tableNode,
             tableNode.setOutputVersioned(materializedInternal.storeSupplier() 
instanceof VersionedBytesStoreSupplier);
         }
     }
+
+    private static class SubscriptionSinkPartitioner<K, KO> implements 
StreamPartitioner<KO, SubscriptionWrapper<K>> {
+        private final StreamPartitioner<KO, Void> otherPartitioner;
+        private final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition;
+
+        private SubscriptionSinkPartitioner(
+            final StreamPartitioner<KO, Void> otherPartitioner,
+            final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition
+        ) {
+            this.otherPartitioner = otherPartitioner;
+            this.getPartition = getPartition;
+        }
+
+        @SuppressWarnings("removal")
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic, final KO 
key, final SubscriptionWrapper<K> value, final int numPartitions) {
+            return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);

Review Comment:
   Given that this is all internal code, and we know that KS should never call 
the deprecated overload, I am wondering if we should not forward the call here, 
but throw an exception to catch any potential bugs?



##########
streams/src/main/java/org/apache/kafka/streams/kstream/internals/KTableImpl.java:
##########
@@ -1438,4 +1436,78 @@ private static void maybeSetOutputVersioned(final 
GraphNode tableNode,
             tableNode.setOutputVersioned(materializedInternal.storeSupplier() 
instanceof VersionedBytesStoreSupplier);
         }
     }
+
+    private static class SubscriptionSinkPartitioner<K, KO> implements 
StreamPartitioner<KO, SubscriptionWrapper<K>> {
+        private final StreamPartitioner<KO, Void> otherPartitioner;
+        private final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition;
+
+        private SubscriptionSinkPartitioner(
+            final StreamPartitioner<KO, Void> otherPartitioner,
+            final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition
+        ) {
+            this.otherPartitioner = otherPartitioner;
+            this.getPartition = getPartition;
+        }
+
+        @SuppressWarnings("removal")
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic, final KO 
key, final SubscriptionWrapper<K> value, final int numPartitions) {
+            return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);
+        }
+
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic,
+                                                 final KO key,
+                                                 final SubscriptionWrapper<K> 
value,
+                                                 final Headers headers,
+                                                 final int numPartitions) {
+            return getPartition.apply(otherPartitioner.partitions(topic, key, 
null, headers, numPartitions));
+        }
+    }
+
+    private static class ForeignResponseSinkPartitioner<K, VO> implements 
StreamPartitioner<K, SubscriptionResponseWrapper<VO>> {
+        private final StreamPartitioner<K, Void> partitioner;
+        private final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition;
+
+        private ForeignResponseSinkPartitioner(
+            final StreamPartitioner<K, Void> partitioner,
+            final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition
+        ) {
+            this.partitioner = partitioner;
+            this.getPartition = getPartition;
+        }
+
+        @SuppressWarnings("removal")
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic, final K 
key, final SubscriptionResponseWrapper<VO> value, final int numPartitions) {
+            return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);
+        }
+
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic,
+                                                 final K key,
+                                                 final 
SubscriptionResponseWrapper<VO> value,
+                                                 final Headers headers,
+                                                 final int numPartitions) {
+            return getPartition.apply(partitioner.partitions(topic, key, null, 
headers, numPartitions));
+        }
+    }
+
+    private static class DefaultForeignResponseSinkPartitioner<K, VO> 
implements StreamPartitioner<K, SubscriptionResponseWrapper<VO>> {
+        @SuppressWarnings("removal")
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic, final K 
key, final SubscriptionResponseWrapper<VO> value, final int numPartitions) {
+            return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);

Review Comment:
   same



##########
streams/src/main/java/org/apache/kafka/streams/processor/internals/DefaultStreamPartitioner.java:
##########
@@ -32,9 +34,15 @@ public DefaultStreamPartitioner(final Serializer<K> 
keySerializer) {
         this.keySerializer = keySerializer;
     }
 
+    @SuppressWarnings({"removal"})
     @Override
     public Optional<Set<Integer>> partitions(final String topic, final K key, 
final V value, final int numPartitions) {
-        final byte[] keyBytes = keySerializer.serialize(topic, key);
+        return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);
+    }
+
+    @Override
+    public Optional<Set<Integer>> partitions(final String topic, final K key, 
final V value, final Headers headers, final int numPartitions) {
+        final byte[] keyBytes = keySerializer.serialize(topic, headers, key);

Review Comment:
   The issue mentioned above by @aliehsaeedii also applies here right? It's not 
limited to `WindowedStreamsPartitioner` as called out on the KIP, but also 
non-windowed case if effected.



##########
streams/src/main/java/org/apache/kafka/streams/KafkaStreams.java:
##########
@@ -1780,38 +1782,70 @@ public Collection<StreamsMetadata> 
streamsMetadataForStore(final String storeNam
         return streamsMetadataState.allMetadataForStore(storeName);
     }
 
+    /**
+     * Finds the metadata containing the active hosts and standby hosts where 
the key being queried would reside,
+     * without requiring record headers to be provided.
+     * <p>
+     * If your partitioner or serializer makes use of headers, use the Headers 
overload, otherwise the returned metadata may not match where the key actually 
resides.
+     * <p>
+     * See {@link #queryMetadataForKey(String, Object, Headers, Serializer)} 
for more details.

Review Comment:
   We can remove this line, when we link inline above



##########
streams/src/main/java/org/apache/kafka/streams/kstream/internals/WindowedStreamPartitioner.java:
##########
@@ -33,21 +34,28 @@ public WindowedStreamPartitioner(final 
WindowedSerializer<K> serializer) {
         this.serializer = serializer;
     }
 
+    @SuppressWarnings({"removal"})
+    @Override
+    public Optional<Set<Integer>> partitions(final String topic, final 
Windowed<K> windowedKey, final V value, final int numPartitions) {
+        return partitions(topic, windowedKey, value, new RecordHeaders(), 
numPartitions);
+    }
+
     /**
      * WindowedStreamPartitioner determines the partition number for a record 
with the given windowed key and value
      * and the current number of partitions. The partition number id 
determined by the original key of the windowed key
      * using the same logic as DefaultPartitioner so that the topic is 
partitioned by the original key.
      *
-     * @param topic the topic name this record is sent to
-     * @param windowedKey the key of the record
-     * @param value the value of the record
+     * @param topic         the topic name this record is sent to
+     * @param windowedKey   the key of the record
+     * @param value         the value of the record
+     * @param headers       the record headers
      * @param numPartitions the total number of partitions
      * @return an integer between 0 and {@code numPartitions-1}, or {@code 
null} if the default partitioning logic should be used
      */
     @Override
-    public Optional<Set<Integer>> partitions(final String topic, final 
Windowed<K> windowedKey, final V value, final int numPartitions) {
+    public Optional<Set<Integer>> partitions(final String topic, final 
Windowed<K> windowedKey, final V value, final Headers headers, final int 
numPartitions) {
         // for windowed key, the key bytes should never be null
-        final byte[] keyBytes = serializer.serializeBaseKey(topic, new 
RecordHeaders(), windowedKey);
+        final byte[] keyBytes = serializer.serializeBaseKey(topic, headers, 
windowedKey);

Review Comment:
   This is a little bit of a pickle... An it's not really limited 
`WindowedSerializer` (which is an internal interface anyway, while the public 
implementations (eg `TimeWindowedSerializer`) are not `final` classes), but 
also the actually key-type serializers a `WindowedSerializer` wraps...



##########
streams/src/main/java/org/apache/kafka/streams/kstream/internals/WindowedStreamPartitioner.java:
##########
@@ -33,21 +34,28 @@ public WindowedStreamPartitioner(final 
WindowedSerializer<K> serializer) {
         this.serializer = serializer;
     }
 
+    @SuppressWarnings({"removal"})
+    @Override
+    public Optional<Set<Integer>> partitions(final String topic, final 
Windowed<K> windowedKey, final V value, final int numPartitions) {
+        return partitions(topic, windowedKey, value, new RecordHeaders(), 
numPartitions);

Review Comment:
   Same question -- this seems to be internal, and thus we should know that 
this method is never called?



##########
streams/src/main/java/org/apache/kafka/streams/KafkaStreams.java:
##########
@@ -1780,38 +1782,70 @@ public Collection<StreamsMetadata> 
streamsMetadataForStore(final String storeNam
         return streamsMetadataState.allMetadataForStore(storeName);
     }
 
+    /**
+     * Finds the metadata containing the active hosts and standby hosts where 
the key being queried would reside,
+     * without requiring record headers to be provided.
+     * <p>
+     * If your partitioner or serializer makes use of headers, use the Headers 
overload, otherwise the returned metadata may not match where the key actually 
resides.
+     * <p>
+     * See {@link #queryMetadataForKey(String, Object, Headers, Serializer)} 
for more details.
+     */
+    public <K> KeyQueryMetadata queryMetadataForKey(final String storeName,
+                                                    final K key,
+                                                    final Serializer<K> 
keySerializer) {
+        return queryMetadataForKey(storeName, key, new RecordHeaders(), 
keySerializer);
+    }
+
     /**
      * Finds the metadata containing the active hosts and standby hosts where 
the key being queried would reside.
      *
      * @param storeName     the {@code storeName} to find metadata for
      * @param key           the key to find metadata for
+     * @param headers       the record headers
      * @param keySerializer serializer for the key
      * @param <K>           key type
      * Returns {@link KeyQueryMetadata} containing all metadata about hosting 
the given key for the given store,
      * or {@code null} if no matching metadata could be found.
      */
     public <K> KeyQueryMetadata queryMetadataForKey(final String storeName,
                                                     final K key,
+                                                    final Headers headers,
                                                     final Serializer<K> 
keySerializer) {
         validateIsRunningOrRebalancing();
-        return streamsMetadataState.keyQueryMetadataForKey(storeName, key, 
keySerializer);
+        return streamsMetadataState.keyQueryMetadataForKey(storeName, key, 
headers, keySerializer);
+    }
+
+    /**
+     * Finds the metadata containing the active hosts and standby hosts where 
the key being queried would reside,
+     * using the supplied partitioner and without requiring record headers to 
be provided.
+     * <p>
+     * If your partitioner or serializer makes use of headers, use the Headers 
overload, otherwise the returned metadata may not match where the key actually 
resides.
+     * <p>
+     * See {@link #queryMetadataForKey(String, Object, Headers, 
StreamPartitioner)} for more details.

Review Comment:
   As above



##########
streams/src/main/java/org/apache/kafka/streams/processor/internals/DefaultStreamPartitioner.java:
##########
@@ -32,9 +34,15 @@ public DefaultStreamPartitioner(final Serializer<K> 
keySerializer) {
         this.keySerializer = keySerializer;
     }
 
+    @SuppressWarnings({"removal"})
     @Override
     public Optional<Set<Integer>> partitions(final String topic, final K key, 
final V value, final int numPartitions) {
-        final byte[] keyBytes = keySerializer.serialize(topic, key);
+        return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);

Review Comment:
   Similar. Should we throw?



##########
streams/src/main/java/org/apache/kafka/streams/kstream/internals/KTableImpl.java:
##########
@@ -1438,4 +1436,78 @@ private static void maybeSetOutputVersioned(final 
GraphNode tableNode,
             tableNode.setOutputVersioned(materializedInternal.storeSupplier() 
instanceof VersionedBytesStoreSupplier);
         }
     }
+
+    private static class SubscriptionSinkPartitioner<K, KO> implements 
StreamPartitioner<KO, SubscriptionWrapper<K>> {
+        private final StreamPartitioner<KO, Void> otherPartitioner;
+        private final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition;
+
+        private SubscriptionSinkPartitioner(
+            final StreamPartitioner<KO, Void> otherPartitioner,
+            final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition
+        ) {
+            this.otherPartitioner = otherPartitioner;
+            this.getPartition = getPartition;
+        }
+
+        @SuppressWarnings("removal")
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic, final KO 
key, final SubscriptionWrapper<K> value, final int numPartitions) {
+            return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);
+        }
+
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic,
+                                                 final KO key,
+                                                 final SubscriptionWrapper<K> 
value,
+                                                 final Headers headers,
+                                                 final int numPartitions) {
+            return getPartition.apply(otherPartitioner.partitions(topic, key, 
null, headers, numPartitions));
+        }
+    }
+
+    private static class ForeignResponseSinkPartitioner<K, VO> implements 
StreamPartitioner<K, SubscriptionResponseWrapper<VO>> {
+        private final StreamPartitioner<K, Void> partitioner;
+        private final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition;
+
+        private ForeignResponseSinkPartitioner(
+            final StreamPartitioner<K, Void> partitioner,
+            final Function<Optional<Set<Integer>>, Optional<Set<Integer>>> 
getPartition
+        ) {
+            this.partitioner = partitioner;
+            this.getPartition = getPartition;
+        }
+
+        @SuppressWarnings("removal")
+        @Override
+        public Optional<Set<Integer>> partitions(final String topic, final K 
key, final SubscriptionResponseWrapper<VO> value, final int numPartitions) {
+            return partitions(topic, key, value, new RecordHeaders(), 
numPartitions);

Review Comment:
   as above



-- 
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