Skip to content

Commit 6a50bbd

Browse files
committed
get rid of technical events in ReservationProcess
Instead, just use exception to pass unavailable products list
1 parent 675fa06 commit 6a50bbd

File tree

9 files changed

+36
-50
lines changed

9 files changed

+36
-50
lines changed

ecommerce/pricing/lib/pricing/commands.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ class AcceptOffer < Infra::Command
111111

112112
class RejectOffer < Infra::Command
113113
attribute :order_id, Infra::Types::UUID
114+
attribute :reason, Infra::Types::String
115+
attribute? :unavailable_products, Infra::Types::Array.of(Infra::Types::UUID)
114116

115117
alias aggregate_id order_id
116118
end

ecommerce/pricing/lib/pricing/events.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ class OfferAccepted < Infra::Event
8686

8787
class OfferRejected < Infra::Event
8888
attribute :order_id, Infra::Types::UUID
89+
attribute :reason, Infra::Types::String
90+
attribute? :unavailable_product_ids, Infra::Types::Array.of(Infra::Types::UUID)
8991
end
9092

9193
class OfferExpired < Infra::Event

ecommerce/pricing/lib/pricing/offer.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,13 @@ def accept
137137
)
138138
end
139139

140-
def reject
140+
def reject(reason, unavailable_product_ids)
141141
raise InvalidState.new("Only accepted offer can be rejected") unless @state == :accepted
142-
apply OfferRejected.new(data: { order_id: @id })
142+
apply OfferRejected.new(data: {
143+
order_id: @id,
144+
reason:,
145+
unavailable_product_ids:
146+
})
143147
end
144148

145149
def expire

ecommerce/pricing/lib/pricing/services.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def initialize(event_store)
228228

229229
def call(command)
230230
@repository.with_aggregate(Offer, command.aggregate_id) do |order|
231-
order.reject
231+
order.reject(command.reason, command.unavailable_products)
232232
end
233233
end
234234
end

ecommerce/processes/.mutant.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ matcher:
1818
- Processes::SyncInventoryFromOrdering*
1919
- Processes::NotifyPaymentsAboutOrderValue*
2020
- Processes::ThreePlusOneFree*
21-
- Processes::ReservationProcess#build_state
21+
- Processes::ReservationProcess*
2222
- Processes::ReservationProcess::ProcessState#call
2323
- Processes::DetermineVatRatesOnOrderPlaced*

ecommerce/processes/lib/processes.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
require_relative "../../invoicing/lib/invoicing"
1010
require_relative "../../fulfillment/lib/fulfillment"
1111
require_relative 'processes/confirm_order_on_payment_captured'
12-
require_relative 'processes/events'
1312
require_relative 'processes/release_payment_process'
1413
require_relative 'processes/shipment_process'
1514
require_relative 'processes/determine_vat_rates_on_order_placed'

ecommerce/processes/lib/processes/events.rb

Lines changed: 0 additions & 10 deletions
This file was deleted.

ecommerce/processes/lib/processes/reservation_process.rb

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ module Processes
22
class ReservationProcess
33
include Infra::Retry
44

5+
class SomeInventoryNotAvailable < StandardError
6+
attr_reader :unavailable_products
7+
8+
def initialize(unavailable_products)
9+
@unavailable_products = unavailable_products
10+
end
11+
end
12+
513
def initialize(event_store, command_bus)
614
@event_store = event_store
715
@command_bus = command_bus
@@ -31,21 +39,17 @@ def reserve_stock(state)
3139
unavailable_products << product_id
3240
end
3341

34-
if unavailable_products.empty?
35-
event = ReservationProcessSuceeded.new(data: { order_id: state.order_id })
36-
else
42+
unless unavailable_products.empty?
3743
release_stock(state)
38-
event = ReservationProcessFailed.new(data: { order_id: state.order_id, unavailable_products: unavailable_products })
44+
raise SomeInventoryNotAvailable.new(unavailable_products)
3945
end
40-
event_store.publish(event, stream_name: stream_name(state.order_id))
4146
end
4247

4348
def update_order_state(state)
44-
event_store
45-
.within { yield }
46-
.subscribe(to: ReservationProcessFailed) { reject_order(state) }
47-
.subscribe(to: ReservationProcessSuceeded) { accept_order(state) }
48-
.call
49+
yield
50+
accept_order(state)
51+
rescue SomeInventoryNotAvailable => exc
52+
reject_order(state, exc.unavailable_products)
4953
end
5054

5155
def release_stock(state)
@@ -64,8 +68,10 @@ def accept_order(state)
6468
command_bus.(Fulfillment::RegisterOrder.new(order_id: state.order_id))
6569
end
6670

67-
def reject_order(state)
68-
command_bus.(Pricing::RejectOffer.new(order_id: state.order_id))
71+
def reject_order(state, unavailable_products)
72+
command_bus.(Pricing::RejectOffer.new(
73+
order_id: state.order_id, reason: "Some products were unavailable", unavailable_products: )
74+
)
6975
end
7076

7177
def stream_name(order_id)

ecommerce/processes/test/reservation_process_test.rb

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ class ReservationProcessTest < Test
66

77
def test_happy_path
88
process = ReservationProcess.new(event_store, command_bus)
9-
assert_success_event do
10-
given([offer_accepted]).each { |event| process.call(event) }
11-
end
9+
10+
given([offer_accepted]).each { |event| process.call(event) }
11+
1212
assert_all_commands(
1313
Inventory::Reserve.new(product_id: product_id, quantity: 1),
1414
Inventory::Reserve.new(product_id: another_product_id, quantity: 2),
@@ -33,14 +33,13 @@ def test_rejects_order_and_compensates_stock_when_sth_is_unavailable
3333
enhanced_command_bus = EnhancedFakeCommandBus.new(command_bus, failing_command => Inventory::InventoryEntry::InventoryNotAvailable)
3434
process = ReservationProcess.new(event_store, enhanced_command_bus)
3535

36-
assert_failure_event do
37-
given([offer_accepted]).each { |event| process.call(event) }
38-
end
36+
given([offer_accepted]).each { |event| process.call(event) }
37+
3938
assert_all_commands(
4039
failing_command,
4140
Inventory::Reserve.new(product_id: another_product_id, quantity: 2),
4241
Inventory::Release.new(product_id: another_product_id, quantity: 2),
43-
Pricing::RejectOffer.new(order_id: order_id),
42+
Pricing::RejectOffer.new(order_id: order_id, reason: "Some products were unavailable", unavailable_products: [product_id]),
4443
)
4544
end
4645

@@ -97,21 +96,5 @@ def order_cancelled
9796
}
9897
)
9998
end
100-
101-
def assert_success_event(&block)
102-
assert_events_contain(
103-
"ReservationProcess$#{order_id}",
104-
ReservationProcessSuceeded.new(data: { order_id: order_id }),
105-
&block
106-
)
107-
end
108-
109-
def assert_failure_event(&block)
110-
assert_events_contain(
111-
"ReservationProcess$#{order_id}",
112-
ReservationProcessFailed.new(data: { order_id: order_id, unavailable_products: [product_id] }),
113-
&block
114-
)
115-
end
11699
end
117100
end

0 commit comments

Comments
 (0)