Thank you, Matthias, for the detailed implementation and explanation. As of
now, our capability is limited to executing interactive queries on
individual partitions. To illustrate:

Consider the IQv2StoreIntegrationTest:

We have two partitions:
Partition0 contains key-value pairs: <0,0> and <2,2>.
Partition1 contains key-value pairs: <1,1> and <3,3>.
When executing RangeQuery.withRange(1,3), the results are:

Partition0: [2]
Partition1: [1, 3]
To support functionalities like reverseRange and reverseAll, we can
introduce the withDescendingKeys() method. For instance, using
RangeQuery.withRange(1,3).withDescendingKeys(), the anticipated results are:

Partition0: [2]
Partition1: [3, 1]

In response to Hao's inquiry about the boundary issue, please refer to the
StoreQueryUtils class. The code snippet:

iterator = kvStore.range(lowerRange.orElse(null), upperRange.orElse(null));
indicates that when implementing range in each store, it's structured like:

@Override
public KeyValueIterator<Bytes, byte[]> range(final Bytes from, final Bytes
to) {
    if (from != null && to != null && from.compareTo(to) > 0) {
This section performs the necessary checks.

Sincerely,
Hanyu

On Thu, Oct 5, 2023 at 9:52 AM Hanyu (Peter) Zheng <pzh...@confluent.io>
wrote:

> Hi, Hao,
>
> In this case, it will return an empty set or list in the end.
>
> Sincerely,
> Hanyu
>
> On Wed, Oct 4, 2023 at 10:29 PM Matthias J. Sax <mj...@apache.org> wrote:
>
>> Great discussion!
>>
>> It seems the only open question might be about ordering guarantees?
>> IIRC, we had a discussion about this in the past.
>>
>>
>> Technically (at least from my POV), existing `RangeQuery` does not have
>> a guarantee that data is return in any specific order (not even on a per
>> partitions bases). It just happens that RocksDB (and as pointed out by
>> Hanyu already, also the built-in in-memory store that is base on a
>> tree-map) allows us to return data ordered by key; as mentioned already,
>> this guarantee is limited on a per partition basis.
>>
>> If there would be custom store base on a hashed key-value store, this
>> store could implement RangeQuery and return data (even for a single
>> partition) with no ordering, without violating the contract.
>>
>>
>>
>> Thus, it could actually make sense, to extend `RangeQuery` and allow
>> three options: no-order, ascending, descending. For our existing
>> Rocks/InMemory implementations, no-order could be equal to ascending and
>> nothing changes effectively, but it might be a better API contract? --
>> If we assume that there might be a custom hash-based store, such a store
>> could reject a query if "ascending" is required, or might need to do
>> more work to implement it (up to the store maintainer). This is actually
>> the beauty of IQv2 that different stores can pick what queries they want
>> to support.
>>
>>  From an API contract point of view, it seems confusing to say:
>> specifying nothing means no guarantee (or ascending if the store can
>> offer it), but descending can we explicitly request. Thus, a hash-based
>> store, might be able to accept "order not specified query", but would
>> reject "descending". This seems to be somewhat unbalanced?
>>
>> Thus, I am wondering if we should actually add `withAscendingKeys()`,
>> too, even if it won't impact our current RocksDB/In-Memory
>> implementations?
>>
>>
>> The second question is about per-partition or across-partition ordering:
>> it's not possible right now to actually offer across-partition ordering
>> the way IQv2 is setup. The reason is, that the store that implements a
>> query type, is always a single shard. Thus, the implementation does not
>> have access to other shards. It's hard-coded inside Kafka Streams, to
>> query each shared, and to "accumulate" partial results, and return the
>> back to the user. Note that the API is:
>>
>>
>> > StateQueryResult<R> result = KafkaStreams.query(...);
>> > Map<Integer, QueryResult<R>> resultPerPartitions =
>> result.getPartitionResults();
>>
>>
>> Thus, if we would want to offer across-partition ordering, we cannot do
>> it right now, because Kafka Streams does not know anything about the
>> semantics of the query it distributes... -- the result is an unknown
>> type <R>. We would need to extend IQv2 with an additional mechanism,
>> that allows users to plug in more custom code to "merge" multiple
>> partitions result into a "global result". This is clearly out-of-scope
>> for this KIP and would require a new KIP by itself.
>>
>> I seems that this contract, which is independent of the query type is
>> not well understood, and thus a big +1 to fix the documentation. I don't
>> think that this KIP must "define" anything, but it might of course be
>> worth to add the explanation why the KIP cannot even offer
>> global-ordering, as it's defined/limited by the IQv2 "framework" itself,
>> not the individual queries.
>>
>>
>>
>> -Matthias
>>
>>
>>
>>
>> On 10/4/23 4:38 PM, Hao Li wrote:
>> > Hi Hanyu,
>> >
>> > Thanks for the KIP! Seems there are already a lot of good discussions. I
>> > only have two comments:
>> >
>> > 1. Please make it clear in
>> > ```
>> >      /**
>> >       * Interactive range query using a lower and upper bound to filter
>> the
>> > keys returned.
>> >       * @param lower The key that specifies the lower bound of the range
>> >       * @param upper The key that specifies the upper bound of the range
>> >       * @param <K> The key type
>> >       * @param <V> The value type
>> >       */
>> >      public static <K, V> RangeQuery<K, V> withRange(final K lower,
>> final K
>> > upper) {
>> >          return new RangeQuery<>(Optional.ofNullable(lower),
>> > Optional.ofNullable(upper), true);
>> >      }
>> > ```
>> > that a `null` in lower or upper parameter means it's unbounded.
>> > 2. What's the behavior if lower is 3 and upper is 1? Is it
>> IllegalArgument
>> > or will this return an empty result? Maybe also clarify this in the
>> > document.
>> >
>> > Thanks,
>> > Hao
>> >
>> >
>> > On Wed, Oct 4, 2023 at 9:27 AM Hanyu (Peter) Zheng
>> > <pzh...@confluent.io.invalid> wrote:
>> >
>> >> For testing purposes, we previously used a Set to record the results in
>> >> IQv2StoreIntegrationTest. Let's take an example where we now have two
>> >> partitions and four key-value pairs: <0,0> in p0, <1,1> in p1, <2,2>
>> in p0,
>> >> and <3,3> in p1.
>> >>
>> >> If we execute withRange(1,3), it will return a Set of <1, 2, 3>.
>> However,
>> >> if we run withRange(1,3).withDescendingKeys(), and still use a Set, the
>> >> result will again be a Set of <1,2,3>. This means we won't be able to
>> >> determine whether the results have been reversed.
>> >>
>> >> To resolve this ambiguity, I've switched to using a List to record the
>> >> results, ensuring the order of retrieval from partitions p0 and p1. So,
>> >> withRange(1,3) would yield a List of [2, 1, 3], whereas
>> >> withRange(1,3).withDescendingKeys() would produce a List of [2,3,1].
>> >>
>> >> This ordering makes sense since RocksDB sorts its keys, and
>> InMemoryStore
>> >> uses a TreeMap structure, which means the keys are already sorted.
>> >>
>> >> Sincerely,
>> >> Hanyu
>> >>
>> >> On Wed, Oct 4, 2023 at 9:25 AM Hanyu (Peter) Zheng <
>> pzh...@confluent.io>
>> >> wrote:
>> >>
>> >>> Hi,  Bruno
>> >>>
>> >>> Thank you for your suggestions, I will update them soon.
>> >>> Sincerely,
>> >>>
>> >>> Hanyu
>> >>>
>> >>> On Wed, Oct 4, 2023 at 9:25 AM Hanyu (Peter) Zheng <
>> pzh...@confluent.io>
>> >>> wrote:
>> >>>
>> >>>> Hi, Lucas,
>> >>>>
>> >>>> Thank you for your suggestions.
>> >>>> I will update the KIP and code together.
>> >>>>
>> >>>> Sincerely,
>> >>>> Hanyu
>> >>>>
>> >>>> On Tue, Oct 3, 2023 at 8:16 PM Hanyu (Peter) Zheng <
>> pzh...@confluent.io
>> >>>
>> >>>> wrote:
>> >>>>
>> >>>>> If we use  WithDescendingKeys() to generate a RangeQuery to do the
>> >>>>> reveseQuery, how do we achieve the methods like withRange,
>> >> withUpperBound,
>> >>>>> and withLowerBound only in this method?
>> >>>>>
>> >>>>> On Tue, Oct 3, 2023 at 8:01 PM Hanyu (Peter) Zheng <
>> >> pzh...@confluent.io>
>> >>>>> wrote:
>> >>>>>
>> >>>>>> I believe there's no need to introduce a method like
>> >>>>>> WithDescendingKeys(). Instead, we can simply add a reverse flag to
>> >>>>>> RangeQuery. Each method within RangeQuery would then accept an
>> >> additional
>> >>>>>> parameter. If the reverse is set to true, it would indicate the
>> >> results
>> >>>>>> should be reversed.
>> >>>>>>
>> >>>>>> Initially, I introduced a reverse variable. When set to false, the
>> >>>>>> RangeQuery class behaves normally. However, when reverse is set to
>> >> true,
>> >>>>>> the RangeQuery essentially takes on the functionality of
>> >> ReverseRangeQuery.
>> >>>>>> Further details can be found in the "Rejected Alternatives"
>> section.
>> >>>>>>
>> >>>>>> In my perspective, RangeQuery is a class responsible for creating a
>> >>>>>> series of RangeQuery objects. It offers methods such as withRange,
>> >>>>>> withUpperBound, and withLowerBound, allowing us to generate objects
>> >>>>>> representing different queries. I'm unsure how adding a
>> >>>>>> withDescendingOrder() method would be compatible with the other
>> >> methods,
>> >>>>>> especially considering that, based on KIP 969, WithDescendingKeys()
>> >> doesn't
>> >>>>>> appear to take any input variables. And if withDescendingOrder()
>> >> doesn't
>> >>>>>> accept any input, how does it return a RangeQuery?
>> >>>>>>
>> >>>>>> On Tue, Oct 3, 2023 at 4:37 PM Hanyu (Peter) Zheng <
>> >> pzh...@confluent.io>
>> >>>>>> wrote:
>> >>>>>>
>> >>>>>>> Hi, Colt,
>> >>>>>>> The underlying structure of inMemoryKeyValueStore is treeMap.
>> >>>>>>> Sincerely,
>> >>>>>>> Hanyu
>> >>>>>>>
>> >>>>>>> On Tue, Oct 3, 2023 at 4:34 PM Hanyu (Peter) Zheng <
>> >>>>>>> pzh...@confluent.io> wrote:
>> >>>>>>>
>> >>>>>>>> Hi Bill,
>> >>>>>>>> 1. I will update the KIP in accordance with the PR and
>> synchronize
>> >>>>>>>> their future updates.
>> >>>>>>>> 2. I will use that name.
>> >>>>>>>> 3. you mean add something about ordering at the motivation
>> section?
>> >>>>>>>>
>> >>>>>>>> Sincerely,
>> >>>>>>>> Hanyu
>> >>>>>>>>
>> >>>>>>>>
>> >>>>>>>> On Tue, Oct 3, 2023 at 4:29 PM Hanyu (Peter) Zheng <
>> >>>>>>>> pzh...@confluent.io> wrote:
>> >>>>>>>>
>> >>>>>>>>> Hi, Walker,
>> >>>>>>>>>
>> >>>>>>>>> 1. I will update the KIP in accordance with the PR and
>> synchronize
>> >>>>>>>>> their future updates.
>> >>>>>>>>> 2. I will use that name.
>> >>>>>>>>> 3. I'll provide additional details in that section.
>> >>>>>>>>> 4. I intend to utilize rangeQuery to achieve what we're
>> referring
>> >> to
>> >>>>>>>>> as reverseQuery. In essence, reverseQuery is merely a term. To
>> >> clear up any
>> >>>>>>>>> ambiguity, I'll make necessary adjustments to the KIP.
>> >>>>>>>>>
>> >>>>>>>>> Sincerely,
>> >>>>>>>>> Hanyu
>> >>>>>>>>>
>> >>>>>>>>>
>> >>>>>>>>>
>> >>>>>>>>> On Tue, Oct 3, 2023 at 4:09 PM Hanyu (Peter) Zheng <
>> >>>>>>>>> pzh...@confluent.io> wrote:
>> >>>>>>>>>
>> >>>>>>>>>> Ok, I will change it back to following the code, and update
>> them
>> >>>>>>>>>> together.
>> >>>>>>>>>>
>> >>>>>>>>>> On Tue, Oct 3, 2023 at 2:27 PM Walker Carlson
>> >>>>>>>>>> <wcarl...@confluent.io.invalid> wrote:
>> >>>>>>>>>>
>> >>>>>>>>>>> Hello Hanyu,
>> >>>>>>>>>>>
>> >>>>>>>>>>> Looking over your kip things mostly make sense but I have a
>> >> couple
>> >>>>>>>>>>> of
>> >>>>>>>>>>> comments.
>> >>>>>>>>>>>
>> >>>>>>>>>>>
>> >>>>>>>>>>>     1. You have "withDescandingOrder()". I think you mean
>> >>>>>>>>>>> "descending" :)
>> >>>>>>>>>>>     Also there are still a few places in the do where its
>> called
>> >>>>>>>>>>> "setReverse"
>> >>>>>>>>>>>     2. Also I like "WithDescendingKeys()" better
>> >>>>>>>>>>>     3. I'm not sure of what ordering guarantees we are
>> offering.
>> >>>>>>>>>>> Perhaps we
>> >>>>>>>>>>>     can add a section to the motivation clearly spelling out
>> the
>> >>>>>>>>>>> current
>> >>>>>>>>>>>     ordering and the new offering?
>> >>>>>>>>>>>     4. When you say "use unbounded reverseQuery to achieve
>> >>>>>>>>>>> reverseAll" do
>> >>>>>>>>>>>     you mean "use unbounded RangeQuery to achieve
>> reverseAll"? as
>> >>>>>>>>>>> far as I can
>> >>>>>>>>>>>     tell we don't have a reverseQuery as a named object?
>> >>>>>>>>>>>
>> >>>>>>>>>>>
>> >>>>>>>>>>> Looking good so far
>> >>>>>>>>>>>
>> >>>>>>>>>>> best,
>> >>>>>>>>>>> Walker
>> >>>>>>>>>>>
>> >>>>>>>>>>> On Tue, Oct 3, 2023 at 2:13 PM Colt McNealy <
>> c...@littlehorse.io
>> >>>
>> >>>>>>>>>>> wrote:
>> >>>>>>>>>>>
>> >>>>>>>>>>>> Hello Hanyu,
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> Thank you for the KIP. I agree with Matthias' proposal to
>> keep
>> >>>>>>>>>>> the naming
>> >>>>>>>>>>>> convention consistent with KIP-969. I favor the
>> >>>>>>>>>>> `.withDescendingKeys()`
>> >>>>>>>>>>>> name.
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> I am curious about one thing. RocksDB guarantees that records
>> >>>>>>>>>>> returned
>> >>>>>>>>>>>> during a range scan are lexicographically ordered by the
>> bytes
>> >>>>>>>>>>> of the keys
>> >>>>>>>>>>>> (either ascending or descending order, as specified in the
>> >>>>>>>>>>> query). This
>> >>>>>>>>>>>> means that results within a single partition are indeed
>> >>>>>>>>>>> ordered.** My
>> >>>>>>>>>>>> reading of KIP-805 suggests to me that you don't need to
>> >> specify
>> >>>>>>>>>>> the
>> >>>>>>>>>>>> partition number you are querying in IQv2, which means that
>> you
>> >>>>>>>>>>> can have a
>> >>>>>>>>>>>> valid reversed RangeQuery over a store with "multiple
>> >>>>>>>>>>> partitions" in it.
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> Currently, IQv1 does not guarantee order of keys in this
>> >>>>>>>>>>> scenario. Does
>> >>>>>>>>>>>> IQv2 support ordering across partitions? Such an
>> implementation
>> >>>>>>>>>>> would
>> >>>>>>>>>>>> require opening a rocksdb range scan** on multiple rocksdb
>> >>>>>>>>>>> instances (one
>> >>>>>>>>>>>> per partition), and polling the first key of each. Whether or
>> >>>>>>>>>>> not this is
>> >>>>>>>>>>>> ordered, could we please add that to the documentation?
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> **(How is this implemented/guaranteed in an
>> >>>>>>>>>>> `inMemoryKeyValueStore`? I
>> >>>>>>>>>>>> don't know about that implementation).
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> Colt McNealy
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> *Founder, LittleHorse.dev*
>> >>>>>>>>>>>>
>> >>>>>>>>>>>>
>> >>>>>>>>>>>> On Tue, Oct 3, 2023 at 1:35 PM Hanyu (Peter) Zheng
>> >>>>>>>>>>>> <pzh...@confluent.io.invalid> wrote:
>> >>>>>>>>>>>>
>> >>>>>>>>>>>>> ok, I will update it. Thank you  Matthias
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>> Sincerely,
>> >>>>>>>>>>>>> Hanyu
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>> On Tue, Oct 3, 2023 at 11:23 AM Matthias J. Sax <
>> >>>>>>>>>>> mj...@apache.org>
>> >>>>>>>>>>>> wrote:
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>>> Thanks for the KIP Hanyu!
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> I took a quick look and it think the proposal makes sense
>> >>>>>>>>>>> overall.
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> A few comments about how to structure the KIP.
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> As you propose to not add `ReverseRangQuery` class, the
>> >> code
>> >>>>>>>>>>> example
>> >>>>>>>>>>>>>> should go into "Rejected Alternatives" section, not in the
>> >>>>>>>>>>> "Proposed
>> >>>>>>>>>>>>>> Changes" section.
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> For the `RangeQuery` code example, please omit all existing
>> >>>>>>>>>>> methods
>> >>>>>>>>>>>> etc,
>> >>>>>>>>>>>>>> and only include what will be added/changed. This make it
>> >>>>>>>>>>> simpler to
>> >>>>>>>>>>>>>> read the KIP.
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> nit: typo
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>>   the fault value is false
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> Should be "the default value is false".
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> Not sure if `setReverse()` is the best name. Maybe
>> >>>>>>>>>>>> `withDescandingOrder`
>> >>>>>>>>>>>>>> (or similar, I guess `withReverseOrder` would also work)
>> >>>>>>>>>>> might be
>> >>>>>>>>>>>>>> better? Would be good to align to KIP-969 proposal that
>> >>>>>>>>>>> suggest do use
>> >>>>>>>>>>>>>> `withDescendingKeys` methods for "reverse key-range"; if we
>> >>>>>>>>>>> go with
>> >>>>>>>>>>>>>> `withReverseOrder` we should change KIP-969 accordingly.
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> Curious to hear what others think about naming this
>> >>>>>>>>>>> consistently across
>> >>>>>>>>>>>>>> both KIPs.
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> -Matthias
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>> On 10/3/23 9:17 AM, Hanyu (Peter) Zheng wrote:
>> >>>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>
>> >>>>>>>>>>>
>> >>
>> https://cwiki.apache.org/confluence/display/KAFKA/KIP-985%3A+Add+reverseRange+and+reverseAll+query+over+kv-store+in+IQv2
>> >>>>>>>>>>>>>>>
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>> --
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>> [image: Confluent] <https://www.confluent.io>
>> >>>>>>>>>>>>> Hanyu (Peter) Zheng he/him/his
>> >>>>>>>>>>>>> Software Engineer Intern
>> >>>>>>>>>>>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>>>>>>>>>>> Follow us: [image: Blog]
>> >>>>>>>>>>>>> <
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>
>> >>>>>>>>>>>
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>>>>>>>>>>>>> [image:
>> >>>>>>>>>>>>> Twitter] <https://twitter.com/ConfluentInc>[image:
>> LinkedIn]
>> >>>>>>>>>>>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image:
>> >> Slack]
>> >>>>>>>>>>>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>>>>>>>>>>> <https://youtube.com/confluent>
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>> [image: Try Confluent Cloud for Free]
>> >>>>>>>>>>>>> <
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>
>> >>>>>>>>>>>
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>>>>>>>>>>>>
>> >>>>>>>>>>>>>
>> >>>>>>>>>>>>
>> >>>>>>>>>>>
>> >>>>>>>>>>
>> >>>>>>>>>>
>> >>>>>>>>>> --
>> >>>>>>>>>>
>> >>>>>>>>>> [image: Confluent] <https://www.confluent.io>
>> >>>>>>>>>> Hanyu (Peter) Zheng he/him/his
>> >>>>>>>>>> Software Engineer Intern
>> >>>>>>>>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>>>>>>>> Follow us: [image: Blog]
>> >>>>>>>>>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>>>>>>>>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>>>>>>>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>>>>>>>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>>>>>>>> <https://youtube.com/confluent>
>> >>>>>>>>>>
>> >>>>>>>>>> [image: Try Confluent Cloud for Free]
>> >>>>>>>>>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>>>>>>>>
>> >>>>>>>>>
>> >>>>>>>>>
>> >>>>>>>>> --
>> >>>>>>>>>
>> >>>>>>>>> [image: Confluent] <https://www.confluent.io>
>> >>>>>>>>> Hanyu (Peter) Zheng he/him/his
>> >>>>>>>>> Software Engineer Intern
>> >>>>>>>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>>>>>>> Follow us: [image: Blog]
>> >>>>>>>>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>>>>>>>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>>>>>>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>>>>>>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>>>>>>> <https://youtube.com/confluent>
>> >>>>>>>>>
>> >>>>>>>>> [image: Try Confluent Cloud for Free]
>> >>>>>>>>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>>>>>>>
>> >>>>>>>>
>> >>>>>>>>
>> >>>>>>>> --
>> >>>>>>>>
>> >>>>>>>> [image: Confluent] <https://www.confluent.io>
>> >>>>>>>> Hanyu (Peter) Zheng he/him/his
>> >>>>>>>> Software Engineer Intern
>> >>>>>>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>>>>>> Follow us: [image: Blog]
>> >>>>>>>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>>>>>>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>>>>>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>>>>>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>>>>>> <https://youtube.com/confluent>
>> >>>>>>>>
>> >>>>>>>> [image: Try Confluent Cloud for Free]
>> >>>>>>>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>>>>>>
>> >>>>>>>
>> >>>>>>>
>> >>>>>>> --
>> >>>>>>>
>> >>>>>>> [image: Confluent] <https://www.confluent.io>
>> >>>>>>> Hanyu (Peter) Zheng he/him/his
>> >>>>>>> Software Engineer Intern
>> >>>>>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>>>>> Follow us: [image: Blog]
>> >>>>>>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>>>>>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>>>>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>>>>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>>>>> <https://youtube.com/confluent>
>> >>>>>>>
>> >>>>>>> [image: Try Confluent Cloud for Free]
>> >>>>>>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>>>>>
>> >>>>>>
>> >>>>>>
>> >>>>>> --
>> >>>>>>
>> >>>>>> [image: Confluent] <https://www.confluent.io>
>> >>>>>> Hanyu (Peter) Zheng he/him/his
>> >>>>>> Software Engineer Intern
>> >>>>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>>>> Follow us: [image: Blog]
>> >>>>>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>>>>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>>>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>>>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>>>> <https://youtube.com/confluent>
>> >>>>>>
>> >>>>>> [image: Try Confluent Cloud for Free]
>> >>>>>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>>>>
>> >>>>>
>> >>>>>
>> >>>>> --
>> >>>>>
>> >>>>> [image: Confluent] <https://www.confluent.io>
>> >>>>> Hanyu (Peter) Zheng he/him/his
>> >>>>> Software Engineer Intern
>> >>>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>>> Follow us: [image: Blog]
>> >>>>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>>>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>>> <https://youtube.com/confluent>
>> >>>>>
>> >>>>> [image: Try Confluent Cloud for Free]
>> >>>>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>>>
>> >>>>
>> >>>>
>> >>>> --
>> >>>>
>> >>>> [image: Confluent] <https://www.confluent.io>
>> >>>> Hanyu (Peter) Zheng he/him/his
>> >>>> Software Engineer Intern
>> >>>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>>> Follow us: [image: Blog]
>> >>>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>>> <https://youtube.com/confluent>
>> >>>>
>> >>>> [image: Try Confluent Cloud for Free]
>> >>>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>>
>> >>>
>> >>>
>> >>> --
>> >>>
>> >>> [image: Confluent] <https://www.confluent.io>
>> >>> Hanyu (Peter) Zheng he/him/his
>> >>> Software Engineer Intern
>> >>> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >>> Follow us: [image: Blog]
>> >>> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >>> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >>> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >>> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >>> <https://youtube.com/confluent>
>> >>>
>> >>> [image: Try Confluent Cloud for Free]
>> >>> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>>
>> >>
>> >>
>> >> --
>> >>
>> >> [image: Confluent] <https://www.confluent.io>
>> >> Hanyu (Peter) Zheng he/him/his
>> >> Software Engineer Intern
>> >> +1 (213) 431-7193 <+1+(213)+431-7193>
>> >> Follow us: [image: Blog]
>> >> <
>> >>
>> https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog
>> >>> [image:
>> >> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
>> >> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
>> >> <https://slackpass.io/confluentcommunity>[image: YouTube]
>> >> <https://youtube.com/confluent>
>> >>
>> >> [image: Try Confluent Cloud for Free]
>> >> <
>> >>
>> https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic
>> >>>
>> >>
>> >
>>
>
>
> --
>
> [image: Confluent] <https://www.confluent.io>
> Hanyu (Peter) Zheng he/him/his
> Software Engineer Intern
> +1 (213) 431-7193 <+1+(213)+431-7193>
> Follow us: [image: Blog]
> <https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog>[image:
> Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
> <https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
> <https://slackpass.io/confluentcommunity>[image: YouTube]
> <https://youtube.com/confluent>
>
> [image: Try Confluent Cloud for Free]
> <https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic>
>


-- 

[image: Confluent] <https://www.confluent.io>
Hanyu (Peter) Zheng he/him/his
Software Engineer Intern
+1 (213) 431-7193 <+1+(213)+431-7193>
Follow us: [image: Blog]
<https://www.confluent.io/blog?utm_source=footer&utm_medium=email&utm_campaign=ch.email-signature_type.community_content.blog>[image:
Twitter] <https://twitter.com/ConfluentInc>[image: LinkedIn]
<https://www.linkedin.com/in/hanyu-peter-zheng/>[image: Slack]
<https://slackpass.io/confluentcommunity>[image: YouTube]
<https://youtube.com/confluent>

[image: Try Confluent Cloud for Free]
<https://www.confluent.io/get-started?utm_campaign=tm.fm-apac_cd.inbound&utm_source=gmail&utm_medium=organic>

Reply via email to