Fork me on GitHub
#architecture
<
2024-03-30
>
apbleonard00:03:49

In the context of stateful event processing would you say idempotency implies commutativity? IOW if some event has to have the same effect on the state when processed twice ("idempotence"), surely that includes receiving that second event waaay after the first, potentially after other intervening events have been processed, and so it must have the same effect out of order too ("commutativity")? (Sorry - not a very Clojure-y question!)

Max02:03:34

Depends a lot on the specifics. Assuming a totally ordered event stream, when event validity is determined by stream index, commutativity is trivially disprovable: 1. A is true 2. A is false 3. Redelivery of event 1 A is now false, but it should be true. These events are idempotent: if the delivery order was 1, 3, 2 it would’ve been fine. Of course you determine event validity differently, but doing so gets into other thorny issues. You might think to attach a timestamp to each event, but that brings in issues with clock drift and granularity. Any solution eventually has to contend with the fundamental limitations with uncoordinated simultaneity. Etc etc Most approaches I’ve seen make a single system the arbiter of total ordering and use an event’s index in that order as its source of truth. That makes double-delivery on receivers a non-issue (just ignore everything from before your most recent event) but not from double-delivery from event producers to the total ordering arbiter.

👍 1
apbleonard23:03:54

In my more idealistic times I looked at vector clocks for some sense of distributed total ordering, only to realise that all this can tell you is whether some event was before another or effectively simultaneous, and potentially therefore conflicting, requiring business decisions on how to resolve it. It also looked impossibly fragile.... But that's an aside. Yes I was thinking about a totally ordered event stream from a single producer where events carried a monotonically increasing index or sequence number allowing consumers to spot out of order events. I think when most people say "make your event processing idempotent" they do not consider the disordered case, though they also advocate commutativity (where that fits your use case) but as a completely separate thing.

Max23:03:29

Yeah in that situation, idempotency definitely does not imply commutativity.

raspasov15:04:12

In certain cases, you can achieve both: take an append-only set. All additions to the set are idempotent – set stays the same; and the order of the additions does not matter for the end result. But in many other cases, it does not… Say adding numbers: a + b = b + a (commutative). But if you add b twice then: a + b + b != b + a (not idempotent)

raspasov15:04:56

I think idempotency in practice requires storage/state but somebody correct me if I am wrong 🙂 vs. commutativity does not.

apbleonard15:04:36

I loved this talk on coordination free aggregation (requires free login). It's from an academic who proposed then proved the CALM theorem which is the basis for CRDTs etc. He doesn't shy away from complex stuff but is still a very good speaker on the subject :) https://vimeo.com/53904989

apbleonard15:04:28

To get back to my original question, I said above that "...I was thinking about a totally ordered event stream from a single producer where events carried a monotonically increasing index or sequence number allowing consumers to spot out of order events..." Hmm in that case it's easy and idempotency needn't require commutativity. Let's consider the other case where events come from multiple producers where events do not carry a monotonically increasing index or sequence number allowing consumers to spot out of order events (as coordinating that single sequence between multiple producers is hard.) Then does idempotency require commutativity? I think it does. When folks talk about the need for idempotency I don't see them discussing this nuance much.

raspasov21:04:37

Then does idempotency require commutativity?I think “require” is relative to the use case. In many cases yes, it does. But I can imagine a case where it does not. In any case, if I can ensure both idempotency and commutativity it certainly makes one’s life more worry-free. I think those are underused aspect in distributed systems where often people reach for centralized coordination (ZooKeeper, etcd, etc) where they can likely get away with simpler solutions – it’s often easier to rely on coordination but it does make for a more complex system.