Hello Jun, 

Thanks for the reply,

JR46: I have clarified the behavior for null and empty values, so users can 
understand the reasoning behind disallowing empty lists. 

JR48: I've updated the KIP accordingly.

Best Regards,
Jiunn-Yang

> Jun Rao <j...@confluent.io.INVALID> 於 2025年8月5日 凌晨12:45 寫道:
> 
> Hi, Jiunn-Yang,
> 
> Thanks for the reply.
> 
> JR46. "Currently, if plugin.path is set to an empty list, no user-specified
> plugin locations are processed, but plugins from the parent classloader are
> still loaded." Could you add why the current behavior is bad for the users?
> 
> JR48. If we want to preserve the current behavior, we should remove the
> following validation, right?
>        if (validStrings.length == 0) {
>            throw new IllegalArgumentException("Valid strings list cannot
> be empty for in validator");
> 
> Jun
> 
> On Fri, Aug 1, 2025 at 6:47 PM 黃竣陽 <s7133...@gmail.com> wrote:
> 
>> Hello Jun,
>> 
>> Thanks for the reply.
>> 
>> JR42, JR45, JR46, JR47: I have updated the KIP.
>> 
>> JR43: If bootstrap.servers is empty for these configurations,
>> it will fail when creating the AdminClient. I have updated the KIP to
>> reflect this behavior.
>> 
>> JR44: Thanks for pointing this out. Kafka will indeed fail at the storage
>> format phase
>> if the configuration is invalid. I have updated the KIP accordingly.
>> 
>> JR48: The current in() method allows empty lists by default, so I believe
>> setting isEmptyAllowed to true
>> better preserves the original behavior. Therefore, I prefer not to change
>> this default.
>> 
>> Best Regards,
>> Jiunn-Yang
>> 
>>> Jun Rao <j...@confluent.io.INVALID> 於 2025年8月2日 凌晨2:38 寫道:
>>> 
>>> Hi, Jiunn-Yang,
>>> 
>>> Thanks for the reply. A few more comments.
>>> 
>>> JR42. [6] [7] are not needed since currently an empty list already causes
>>> an exception.
>>> 
>>> JR43. Could you document the current behavior when bootstrap.servers is
>>> empty in MirrorClientConfig and WorkerConfig?
>>> 
>>> JR44. [12] seems incorrect. I set log.dir, but left log.dirs empty and
>> got
>>> the following.
>>> bin/kafka-storage.sh format --standalone -t $KAFKA_CLUSTER_ID -c
>>> config/server.properties
>>> Exception in thread "main" java.lang.IllegalArgumentException:
>> requirement
>>> failed: At least one log directory must be defined via log.dirs or
>> log.dir.
>>> 
>>> bin/kafka-server-start.sh config/server.properties
>>> [2025-08-01 11:31:20,097] INFO Registered
>>> `kafka:type=kafka.Log4jController` MBean
>>> (kafka.utils.Log4jControllerRegistration$)
>>> [2025-08-01 11:31:20,238] ERROR Exiting Kafka due to fatal exception
>>> (kafka.Kafka$)
>>> java.lang.IllegalArgumentException: requirement failed: At least one log
>>> directory must be defined via log.dirs or log.dir.
>>> 
>>> JR45. Could you group all configs for WorkerConfig together?
>>> 
>>> JR46. plugin.path: We have the following code. So, currently, it seems
>> that
>>> an empty list is allowed for plugin.path and we treat it by adding the
>>> parent path of the classloader. It would be useful to justify why
>>> disallowing empty is better for the users.
>>> 
>>>   public static Set<PluginSource> pluginSources(Set<Path>
>>> pluginLocations, ClassLoader classLoader, PluginClassLoaderFactory
>> factory)
>>> {
>>>       Set<PluginSource> pluginSources = new LinkedHashSet<>();
>>>       for (Path pluginLocation : pluginLocations) {
>>>           try {
>>>               pluginSources.add(isolatedPluginSource(pluginLocation,
>>> classLoader, factory));
>>>           } catch (InvalidPathException | MalformedURLException e) {
>>>               log.error("Invalid path in plugin path: {}. Ignoring.",
>>> pluginLocation, e);
>>>           } catch (IOException e) {
>>>               log.error("Could not get listing for plugin path: {}.
>>> Ignoring.", pluginLocation, e);
>>>           }
>>>       }
>>>       pluginSources.add(classpathPluginSource(classLoader.getParent()));
>>>       return pluginSources;
>>>   }
>>> 
>>> JR47. typo in "Should not allow setting validStrings is empty"
>>> 
>>> JR48. We should pass in isEmptyAllowed as false in the code below, right?
>>>   public static ValidList in(String... validStrings) {
>>>       if (validStrings.length == 0) {
>>>           throw new IllegalArgumentException("Valid strings list cannot
>>> be empty for in validator");
>>>       }
>>>       return new ValidList(List.of(validStrings), true, false);
>>>   }
>>> 
>>> Jun
>>> 
>>> On Tue, Jul 29, 2025 at 8:53 AM 黃竣陽 <s7133...@gmail.com> wrote:
>>> 
>>>> Hello Jun,
>>>> 
>>>> Sorry for the late reply,
>>>> 
>>>> JR40, JR41: I have updated the KIP based on your comments. Please take a
>>>> look.
>>>> 
>>>> Best Regards,
>>>> Jiunn-Yang
>>>> 
>>>>> Jun Rao <j...@confluent.io.INVALID> 於 2025年7月24日 凌晨2:56 寫道:
>>>>> 
>>>>> Hi, Jiunn-Yang,
>>>>> 
>>>>> Thanks for the reply.
>>>>> 
>>>>> JR40. In the table, there are a few configs for which we now disallow
>>>> empty
>>>>> lists. It would be useful to document the current behavior for each of
>>>> them
>>>>> more accurately. It seems that they should all lead to some bad
>> behavior.
>>>>> For example, if log.dirs is empty, it seems that we can't create
>> topics?
>>>>> If group.coordinator.rebalance.protocols is empty, the group rebalance
>>>>> protocol will fail?
>>>>> 
>>>>> JR41. It would be useful to clean up the "Compatibility, Deprecation,
>> and
>>>>> Migration Plan" section a bit.
>>>>> JR41.1 The migration plan has "Introduce a new properties
>> isEmptyAllowed
>>>> ,
>>>>> isNullAllowed", which needs to be changed.
>>>>> JR41.2 It started with "For users who configure an empty list", but not
>>>> all
>>>>> the bullet points are about empty lists.
>>>>> JR41.3 To me, it would be useful to summarize why the behavior changes
>>>> are
>>>>> justified. We made 3 types of changes. (1) Disallow null. This is ok
>>>> since
>>>>> one can't really set a null value through a config file. (2) Disallow
>>>>> duplicates. This is ok since it's rare and confusing. (3) Disallow
>> empty.
>>>>> Ideally, we want to claim that for those cases, they all lead to some
>>>> other
>>>>> errors or had behavior currently.
>>>>> 
>>>>> Jun
>>>>> 
>>>>> On Wed, Jul 23, 2025 at 4:42 AM 黃竣陽 <s7133...@gmail.com> wrote:
>>>>> 
>>>>>> Hello Jun,
>>>>>> 
>>>>>> Thanks for the reply.
>>>>>> 
>>>>>> JR34 ,JR36, JR39: I’ve updated the KIP to reflect these changes.
>>>>>> 
>>>>>> JR38: I clarified the following configurations:
>>>>>> early.start.listeners: This config is optional and allows both null
>> and
>>>>>> empty lists.
>>>>>> log.dirs and plugin.path: These are also optional, but only allow
>>>>>> null—empty lists are not permitted.
>>>>>> 
>>>>>> Best Regards,
>>>>>> Jiunn-Yang
>>>>>> 
>>>>>>> Jun Rao <j...@confluent.io.INVALID> 於 2025年7月23日 凌晨2:28 寫道:
>>>>>>> 
>>>>>>> Hi, Jiunn-Yang and Chia-Ping,
>>>>>>> 
>>>>>>> Thanks for the reply.
>>>>>>> 
>>>>>>> JR34. Sounds good.
>>>>>>> 
>>>>>>> JR36. Could you document that the default value for
>>>>>>> sasl.oauthbearer.expected.audience and ssl.cipher.suites have been
>>>>>> changed?
>>>>>>> 
>>>>>>> JR38. My concern wasn't quite addressed. "If the configuration is
>>>>>> optional,
>>>>>>> we will reject any duplicate values in the list." This implies that
>> if
>>>> a
>>>>>>> config is optional, we allow empty lists. However, for plugin.path,
>> we
>>>>>>> reject empty lists.
>>>>>>> 
>>>>>>> JR39. We can remove the fields isEmptyAllowed and isNullAllowed since
>>>>>> they
>>>>>>> are not public facing.
>>>>>>> 
>>>>>>> Jun
>>>>>>> 
>>>>>>> 
>>>>>>> On Tue, Jul 22, 2025 at 4:26 AM 黃竣陽 <s7133...@gmail.com> wrote:
>>>>>>> 
>>>>>>>> Hello Jun, Chia,
>>>>>>>> 
>>>>>>>> Thanks for the reply,
>>>>>>>> 
>>>>>>>> JR36: I’ve updated the following configurations:
>>>>>>>> - sasl.oauthbearer.expected.audience
>>>>>>>> - ssl.cipher.suites
>>>>>>>> - ssl.enabled.protocols
>>>>>>>> These now allow both empty and non-empty lists. Since the default
>>>> values
>>>>>>>> of
>>>>>>>> sasl.oauthbearer.expected.audience and ssl.cipher.suites were
>>>> previously
>>>>>>>> null,
>>>>>>>> I’ve updated their defaults to List.of() for consistency.
>>>>>>>> 
>>>>>>>> JR37: A ClassCastException does not occur in MirrorClientConfig and
>> it
>>>>>>>> should be none.
>>>>>>>> I’ve updated this in the KIP.
>>>>>>>> 
>>>>>>>> JR38 & JR40: I’ve added a note below the table to indicate which
>>>>>>>> configurations require special attention.
>>>>>>>> 
>>>>>>>> JR39: Yes, these properties are package-private.
>>>>>>>> 
>>>>>>>> Best Regards,
>>>>>>>> Jiunn-Yang
>>>>>>>> 
>>>>>>>>> Chia-Ping Tsai <chia7...@gmail.com> 於 2025年7月22日 下午6:04 寫道:
>>>>>>>>> 
>>>>>>>>> JR34. Hmm, it seems that the code in taskConfigs() could return an
>>>>>> empty
>>>>>>>>> list for a task if knownSourceTopicPartitions is less than
>> maxTasks,
>>>>>>>>> Chia-Ping?
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> Yes, `MirrorSourceConnector#taskConfigs` could return an empty
>> list,
>>>>>>>> which
>>>>>>>>> means no `MirrorSourceTask` can be created.
>>>>>>>>> 
>>>>>>>>> By contrast, if any `MirrorSourceTask` is created, the configs used
>>>> by
>>>>>>>>> `MirrorSourceTask` must contain `task.assigned.partitions` with a
>>>>>>>> non-empty
>>>>>>>>> value.
>>>>>>>>> 
>>>>>>>>> Jun Rao <j...@confluent.io.invalid> 於 2025年7月22日 週二 上午5:14寫道:
>>>>>>>>> 
>>>>>>>>>> Hi, Jiunn-Yang and Chia-Ping,
>>>>>>>>>> 
>>>>>>>>>> Thanks for the reply.
>>>>>>>>>> 
>>>>>>>>>> JR34. Hmm, it seems that the code in taskConfigs() could return an
>>>>>> empty
>>>>>>>>>> list for a task if knownSourceTopicPartitions is less than
>> maxTasks,
>>>>>>>>>> Chia-Ping?
>>>>>>>>>> 
>>>>>>>>>> JR36. Sounds good. Could you update the KIP? Also, should we do
>> the
>>>>>> same
>>>>>>>>>> for ssl.cipher.suites and sasl.oauthbearer.expected.audience?
>>>>>>>>>> 
>>>>>>>>>> JR37. Is it true that MirrorClientConfig.bootstrap.servers returns
>>>>>>>>>> ClassCastException for null? It seems that null could be casted to
>>>> any
>>>>>>>>>> class.
>>>>>>>>>> 
>>>>>>>>>> JR38. "If the configuration is optional, we will reject any
>>>> duplicate
>>>>>>>>>> values in the list." Could you clarify this? For example,
>>>> plugin.path
>>>>>> is
>>>>>>>>>> optional, but with a default value. We reject duplicates as well
>> as
>>>>>>>> empty
>>>>>>>>>> lists.
>>>>>>>>>> 
>>>>>>>>>> JR39. isEmptyAllowed and isNullAllowed are not public fields,
>> right?
>>>>>>>> They
>>>>>>>>>> are only public in the anyNonDuplicateValues() method.
>>>>>>>>>> 
>>>>>>>>>> JR40. It would be useful to mention that if cleanup.policy is
>> empty
>>>>>> and
>>>>>>>>>> remote.storage.enable is true, the local log segments will be
>>>> cleaned
>>>>>>>> based
>>>>>>>>>> on log.local.retention.bytes and log.local.retention.ms.
>>>>>>>>>> 
>>>>>>>>>> Jun
>>>>>>>>>> 
>>>>>>>>>> On Fri, Jul 18, 2025 at 9:52 AM Chia-Ping Tsai <
>> chia7...@gmail.com>
>>>>>>>> wrote:
>>>>>>>>>> 
>>>>>>>>>>>> 
>>>>>>>>>>>> JR34: For these two configurations, setting an empty list feels
>> a
>>>>>> bit
>>>>>>>>>>>> unintuitive. If an empty list is
>>>>>>>>>>>> provided, the consumer will call the unsubscribe method, which
>>>>>> doesn't
>>>>>>>>>>>> seem appropriate given
>>>>>>>>>>>> the documentation states: "Topic-partitions assigned to this
>> task
>>>> to
>>>>>>>>>>>> replicate."
>>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> agreed. Additionally, the source code [0] shows that it is not
>>>>>> intended
>>>>>>>>>> to
>>>>>>>>>>> generate empty tps for the source task
>>>>>>>>>>> 
>>>>>>>>>>> [0]
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> https://github.com/apache/kafka/blob/9b542b6ea21e84677a9292f250fc25f8b4162e6f/connect/mirror/src/main/java/org/apache/kafka/connect/mirror/MirrorSourceConnector.java#L202
>>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>>>> 
>>>> 
>>>> 
>> 
>> 

Reply via email to