Skip to content

Commit 7e5d8f6

Browse files
TotalOrderValue as a summary event
In the past, we've had 2 attempts to calculate total value. 1. Keep everything in one aggregate so that it's able to calculate total. Trigger this via command to Calculate so that the Calculated event is published 2. Keep everything in one aggregate, but publish total value as part of all events that change the state of the aggregate. Total value attribute would exist in many events. Some calculation also happened in read models. Both mentioned solutions still co-exist in the codebase. This new attempt tries to move the calculation to a separate building block. I call it a process, for the lack of a better word. It could be also called a summary event builder. https://verraes.net/2019/05/patterns-for-decoupling-distsys-summary-event/ The idea is to subscribe to many events and whenever anything important changes - recalculate and isse TotalOrderValueUpdated. If this new attempt works, then we could get rid of both previous attempts. It can also allow us to have smaller aggregates. One direction it will allow is to consider each Order Line to be an aggregate. This is still WIP, just to show the direction and grab feedback.
1 parent dc19cfb commit 7e5d8f6

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module Processes
2+
class TotalOrderValue
3+
def initialize(event_store)
4+
@event_store = event_store
5+
@total_value = 0
6+
end
7+
8+
def call(event)
9+
case event
10+
when Pricing::PriceItemAdded
11+
@total_value += event.data.fetch(:price)
12+
@order_id = event.data.fetch(:order_id)
13+
end
14+
publish_total_order_value
15+
end
16+
17+
private
18+
19+
def publish_total_order_value
20+
@event_store.publish(
21+
TotalOrderValueUpdated.new(data: { total_value: @total_value, order_id: @order_id }),
22+
stream_name: "Processes::TotalOrderValue$#{@order_id}"
23+
)
24+
end
25+
end
26+
27+
end
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Processes
2+
class TotalOrderValueUpdated < Infra::Event
3+
end
4+
end
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
require "test_helper"
2+
3+
module Processes
4+
class TotalOrderValueTest < ProcessTest
5+
cover "Processes::TotalOrderValue"
6+
7+
def test_total_order_value_calculation
8+
process = TotalOrderValue.new(event_store)
9+
10+
assert_events_contain(
11+
"Processes::TotalOrderValue$#{price_item_added.data[:order_id]}",
12+
Processes::TotalOrderValueUpdated.new(
13+
data: {
14+
total_value: 100,
15+
order_id: order_id
16+
}
17+
)) do
18+
process.call(price_item_added)
19+
end
20+
21+
22+
23+
end
24+
25+
private
26+
27+
def price_item_added
28+
Pricing::PriceItemAdded.new(data: {
29+
order_id: order_id,
30+
item_id: SecureRandom.uuid,
31+
price: 100,
32+
product_id: SecureRandom.uuid,
33+
base_price: 100,
34+
base_total_value: 100,
35+
total_value: 100
36+
})
37+
end
38+
end
39+
end

0 commit comments

Comments
 (0)