You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@kafka.apache.org by Matt Stern <mj...@gmail.com> on 2020/11/06 19:06:39 UTC

KTable "compare and swap"

Hello all,

I am curious if it's possible to use the Streams DSL to perform a "compare
and swap" operation. To give a concrete example:

   - User orders are written to an input topic
   - Our Kafka Streams app reads the order topic and sends each order for
   processing.
   - For a given user, only one order can be sent for processing at a time.
   If a user sends another order while a previous order is still processing,
   we reject it.

I was thinking of using a KTable to store the "state" of each user, where
the key is a user ID and the value is whether an order is out for
processing.

When a new order comes in, we would do a conceptual "compare and swap" on
its value -- if we change the value from false to true, then we send the
order for processing. Otherwise, we "reject" the order.

Looking at it another way, we are using our KTable as a per-user state
machine and we want to respond to particular state changes (e.g. no order
processing -> order processing).

Based on Stack Overflow, it seems like this is possible with the Processor
API (1
<https://stackoverflow.com/questions/49492736/writing-directly-to-a-kafka-state-store>,
2 <https://stackoverflow.com/a/58747230>), but I am curious if it is
possible or recommended to do this with the Streams DSL.

Thanks!
Matt

Re: KTable "compare and swap"

Posted by Matt Stern <mj...@gmail.com>.
I'm wondering if the following works:

   - Make the KTable value a Pair<Event, Event>, where Event is some enum
   like {NO_ORDER, ORDER_RECEIVED, ORDER_PROCESSED}
   - This pair will store the last two events that occurred for a
   particular user.
   - We use the reduce() function to change the Pair value:
      - Suppose for user U, we start with <NO_ORDER, NO_ORDER>
      - When we get an order, we use reduce() to update the KTable value to
      <ORDER_RECEIVED, NO_ORDER>
      - When we get another order, we use reduce() to update the KTable to
      <ORDER_RECEIVED, ORDER_RECEIVED>
      - When an order is processed, we use reduced() to update the KTable
      to <ORDER_PROCESSED, ORDER_RECEIVED>

Now, we can pass the KTable into a filter() operation and send out
processing requests only when the KTable value is <ORDER_RECEIVED,
NO_ORDER> or <ORDER_RECEIVED, ORDER_PROCESSED>.

On Fri, Nov 6, 2020 at 2:06 PM Matt Stern <mj...@gmail.com> wrote:

> Hello all,
>
> I am curious if it's possible to use the Streams DSL to perform a "compare
> and swap" operation. To give a concrete example:
>
>    - User orders are written to an input topic
>    - Our Kafka Streams app reads the order topic and sends each order for
>    processing.
>    - For a given user, only one order can be sent for processing at a
>    time. If a user sends another order while a previous order is still
>    processing, we reject it.
>
> I was thinking of using a KTable to store the "state" of each user, where
> the key is a user ID and the value is whether an order is out for
> processing.
>
> When a new order comes in, we would do a conceptual "compare and swap" on
> its value -- if we change the value from false to true, then we send the
> order for processing. Otherwise, we "reject" the order.
>
> Looking at it another way, we are using our KTable as a per-user state
> machine and we want to respond to particular state changes (e.g. no order
> processing -> order processing).
>
> Based on Stack Overflow, it seems like this is possible with the Processor
> API (1
> <https://stackoverflow.com/questions/49492736/writing-directly-to-a-kafka-state-store>,
> 2 <https://stackoverflow.com/a/58747230>), but I am curious if it is
> possible or recommended to do this with the Streams DSL.
>
> Thanks!
> Matt
>