...
Code Block |
---|
1) LHS sends (CombinedKey(FK-1,Key), SubscriptionWrapper(value=null, instruction=DELETE_KEY_NO_PROPAGATE)) to RHS-1 2) LHS sends (CombinedKey(FK-2,Key), SubscriptionWrapper(value=NewValueHash, instruction=PROPAGATE_NULL_IF_NO_FK_VAL_AVAILABLE)) to RHS-2 3) RHS-1 deletes CombinedKey(FK-1,Key) from state store, but does not propagate any other event. 4) RHS-2 updates the local Key-Value store with (CombinedKey(FK-2,Key), NewValueHash). 5) RHS-2 looks up FK-2 in the RHS-2 materialized state store: a) If a non-null result is obtained, RHS-2 propagates to LHS: (Key, SubscriptionResponseWrapper(NewValueHash, RHS-Result, propagateIfNull=false)) b) If a null result is obtained, RHS-2 propagates to LHS: (Key, SubscriptionResponseWrapper(NewValueHash, null, propagateIfNull=true)) - This is done to ensure that the old join results are wiped out, since that join result is now stale/incorrect. 6) LHS validates that the NewValueHash from the SubscriptionResponseWrapper matches the hash of the current key in the LHS table. a) If the hash doesn't match, discard the event and return. b) If the hash does match, proceed to next step. 7) LHS checks if RHS-result == null and propagateIfNull is true. a) If yes, then propagate out a (Key, null) and return b) If no, proceed to next step. 8) Reminder: RHS-result is not null, and NewValueHash is valid and current. LHS performs the join logic on (LHS-Value and RHS-Result), and outputs the resultant event (Key, joinResult(LHS-Value, RHS-Result)) |
The workflow of LHS-generated changes to outputs is shown below. Each step is cumulative with the previous step. Note that the only real difference between LEFT and INNER is that the LEFT will output when the transition is (k,null) → (k, not-null). Any other transitions from LHS events are identical between Inner and Left join.
LHS Event (key, extracted fk) | To which RHS-partition? | RHS-0 State | RHS-1 State | Inner Join |
---|
Output | Left Join Output | Execute Join Logic? | Notes | Inner-Join SubscriptionWrapper Instruction | |
---|---|---|---|---|---|
Publish new event | (k,1) | RHS-0 | (1,foo) | (k,1,foo) |
(k,1,foo) | Yes, Inner/Left | Normal fk-join induced by LHS event | to RHS-0: | ||||||
Publish update to event by changing fk | (k,1) → (k,2) | RHS-1 | (1,foo) | (k,null) | (k,null) | No | Must indicate a delete because there is currently no (fk,value) in RHS with key=2, and (k,1,foo) is no longer valid output. | to RHS-0: DELETE_KEY_NO_PROPAGATE to RHS-1: | |
Publish update to event | (k,2) → (k,3) | RHS-0 | (1,foo) | (k,null) | (k,null) | No | Ideally would not publish a delete with Inner Join, but we do not maintain sufficient state to know that the (k,2) update resulted in a null output and we don't need to do it again. | to RHS-0: DELETE_KEY_NO_PROPAGATE to RHS-1: | |
Publish a value to RHS |
-0 | - | - | (1,foo) |
(k,3,bar) | (k,3,bar) | Yes, Inner/Left | Performs prefix scan join | - | |||||
Delete k | (k,3) → (k,null) | RHS-0 | (1,foo) | (k,null) | (k,null) | No | Propagate null/delete through the sub-topology | to RHS-0: DELETE_KEY_AND_PROPAGATE | |
Publish original event again | (k,null) → (k,1) | RHS-0 | (1,foo) | (k,1,foo) | (k,1,foo) | Yes, Inner/Left | Normal fk-join induced by LHS event | to RHS-0: | |
Publish to LHS | (q,10) | RHS-1 | (1,foo) | Nothing | (q, null) | LEFT ONLY | Only real difference between Inner and Outer | - | |
Publish a value to RHS-1 | - | - | (1,foo) | (q,baz) | (q,10,baz) | (q,10,baz) | Yes, Inner/Left | Normal fk-join induced by LHS event | to RHS-1: |
Compatibility, Deprecation, and Migration Plan
...