Skip to content

Commit c12e9e1

Browse files
Welcome message sent when a client is registered
This introduces new components: 1. Communication BC (packaged as a gem) 2. Read model for displaying inbox One new process manager: - welcome message process The Communication BC input is only SendMessage command and the output is MessageSent event. The BC and the process manager have their own unit tests. The UI is tested via integration test. In the future we will introduce unit tests for the read model.
1 parent 54996c6 commit c12e9e1

File tree

12 files changed

+280
-2
lines changed

12 files changed

+280
-2
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
requires:
2+
- ./test/test_helper
3+
integration: minitest
4+
usage: opensource
5+
coverage_criteria:
6+
process_abort: true
7+
matcher:
8+
subjects:
9+
- Communication*
10+
ignore:
11+
- Communication::Configuration#call
12+

ecommerce/communication/Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
source "https://rubygems.org"
2+
3+
eval_gemfile "../../infra/Gemfile.test"
4+
gem "infra", path: "../../infra"
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
PATH
2+
remote: ../../infra
3+
specs:
4+
infra (1.0.0)
5+
aggregate_root (~> 2.15)
6+
arkency-command_bus
7+
dry-struct
8+
dry-types
9+
rake
10+
ruby_event_store (~> 2.15)
11+
ruby_event_store-transformations
12+
13+
GEM
14+
remote: https://rubygems.org/
15+
specs:
16+
activesupport (8.0.2)
17+
base64
18+
benchmark (>= 0.3)
19+
bigdecimal
20+
concurrent-ruby (~> 1.0, >= 1.3.1)
21+
connection_pool (>= 2.2.5)
22+
drb
23+
i18n (>= 1.6, < 2)
24+
logger (>= 1.4.2)
25+
minitest (>= 5.1)
26+
securerandom (>= 0.3)
27+
tzinfo (~> 2.0, >= 2.0.5)
28+
uri (>= 0.13.1)
29+
aggregate_root (2.16.0)
30+
ruby_event_store (= 2.16.0)
31+
arkency-command_bus (0.4.1)
32+
concurrent-ruby
33+
ast (2.4.2)
34+
base64 (0.2.0)
35+
benchmark (0.4.0)
36+
bigdecimal (3.1.9)
37+
concurrent-ruby (1.3.5)
38+
connection_pool (2.5.0)
39+
diff-lcs (1.5.1)
40+
drb (2.2.1)
41+
dry-core (1.0.1)
42+
concurrent-ruby (~> 1.0)
43+
zeitwerk (~> 2.6)
44+
dry-inflector (1.0.0)
45+
dry-logic (1.5.0)
46+
concurrent-ruby (~> 1.0)
47+
dry-core (~> 1.0, < 2)
48+
zeitwerk (~> 2.6)
49+
dry-struct (1.6.0)
50+
dry-core (~> 1.0, < 2)
51+
dry-types (>= 1.7, < 2)
52+
ice_nine (~> 0.11)
53+
zeitwerk (~> 2.6)
54+
dry-types (1.7.2)
55+
bigdecimal (~> 3.0)
56+
concurrent-ruby (~> 1.0)
57+
dry-core (~> 1.0)
58+
dry-inflector (~> 1.0)
59+
dry-logic (~> 1.4)
60+
zeitwerk (~> 2.6)
61+
i18n (1.14.7)
62+
concurrent-ruby (~> 1.0)
63+
ice_nine (0.11.2)
64+
logger (1.6.6)
65+
minitest (5.25.0)
66+
mutant (0.12.4)
67+
diff-lcs (~> 1.3)
68+
parser (~> 3.3.0)
69+
regexp_parser (~> 2.9.0)
70+
sorbet-runtime (~> 0.5.0)
71+
unparser (~> 0.6.14)
72+
mutant-minitest (0.12.4)
73+
minitest (~> 5.11)
74+
mutant (= 0.12.4)
75+
parser (3.3.4.2)
76+
ast (~> 2.4.1)
77+
racc
78+
racc (1.8.1)
79+
rake (13.2.1)
80+
regexp_parser (2.9.2)
81+
ruby_event_store (2.16.0)
82+
concurrent-ruby (~> 1.0, >= 1.1.6)
83+
ruby_event_store-transformations (0.1.0)
84+
activesupport (>= 5.0)
85+
ruby_event_store (>= 2.0.0, < 3.0.0)
86+
securerandom (0.4.1)
87+
sorbet-runtime (0.5.11525)
88+
tzinfo (2.0.6)
89+
concurrent-ruby (~> 1.0)
90+
unparser (0.6.15)
91+
diff-lcs (~> 1.3)
92+
parser (>= 3.3.0)
93+
uri (0.13.1)
94+
zeitwerk (2.7.2)
95+
96+
PLATFORMS
97+
arm64-darwin-24
98+
ruby
99+
100+
DEPENDENCIES
101+
infra!
102+
minitest (= 5.25.0)!
103+
mutant-minitest (= 0.12.4)!
104+
105+
BUNDLED WITH
106+
2.6.6

ecommerce/communication/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
install:
2+
@bundle install
3+
4+
test:
5+
@bundle exec ruby -e "require \"rake/rake_test_loader\"" test/*_test.rb
6+
7+
mutate:
8+
@RAILS_ENV=test bundle exec mutant run
9+
10+
.PHONY: install test mutate

ecommerce/communication/README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Communication Module
2+
3+
This module handles communication-related logic for the ecommerce platform.
4+
5+
## Structure
6+
7+
- `lib/` - Main source code for the communication domain
8+
- `test/` - Unit tests for the communication domain
9+
10+
## Development
11+
12+
- Install dependencies: `bundle install`
13+
- Run tests: `make test`
14+
15+
## Testing
16+
17+
Tests are located in the `test/` directory. Use the provided Makefile to run them.
18+
19+
## Mutation Testing
20+
21+
Mutation testing is configured via `.mutant.yml`.
22+
23+
---
24+
25+
For more details on the architecture and DDD approach, see the main [README](../../README.md).
26+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
require "infra"
2+
3+
module Communication
4+
class Configuration
5+
6+
def call(event_store, command_bus)
7+
command_bus.register(SendMessage, OnSendMessage.new(event_store))
8+
end
9+
end
10+
11+
class SendMessage < Infra::Command
12+
attribute :message_id, Infra::Types::UUID
13+
attribute :receiver_id, Infra::Types::UUID
14+
attribute :message, Infra::Types::String
15+
end
16+
17+
class MessageSent < Infra::Event
18+
attribute :message_id, Infra::Types::UUID
19+
attribute :receiver_id, Infra::Types::UUID
20+
attribute :message, Infra::Types::String
21+
end
22+
23+
class OnSendMessage
24+
def initialize(event_store)
25+
@repository = Infra::AggregateRootRepository.new(event_store)
26+
end
27+
28+
def call(command)
29+
@repository.with_aggregate(Message, command.message_id) do |message|
30+
message._send(command.receiver_id, command.message)
31+
end
32+
end
33+
end
34+
35+
class Message
36+
include AggregateRoot
37+
38+
def initialize(id)
39+
@id = id
40+
end
41+
42+
def _send(receiver_id, message)
43+
apply MessageSent.new(
44+
data: {
45+
message_id: @id,
46+
receiver_id: receiver_id,
47+
message: message
48+
}
49+
)
50+
end
51+
52+
def apply_message_sent(_)
53+
end
54+
end
55+
end
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
require_relative "test_helper"
2+
3+
module Communication
4+
class SendingMessageTest < Test
5+
cover "Communication*"
6+
7+
def test_happy_path
8+
expected_event = MessageSent.new(data: {message_id: message_id, receiver_id: receiver_id, message: message_content})
9+
assert_events("Communication::Message$#{message_id}", expected_event) do
10+
send_message
11+
end
12+
end
13+
end
14+
end
15+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
require "minitest/autorun"
2+
require "mutant/minitest/coverage"
3+
4+
require_relative "../lib/communication"
5+
6+
module Communication
7+
class Test < Infra::InMemoryTest
8+
def before_setup
9+
super()
10+
Configuration.new.call(event_store, command_bus)
11+
end
12+
13+
private
14+
15+
def send_message
16+
run_command(SendMessage.new(message_id: message_id, receiver_id: receiver_id, message: message_content))
17+
end
18+
19+
def message_content
20+
"Hello, this is a test message."
21+
end
22+
23+
def receiver_id
24+
@receiver_id ||= SecureRandom.uuid
25+
end
26+
27+
def message_id
28+
@message_id ||= SecureRandom.uuid
29+
end
30+
31+
end
32+
end

ecommerce/configuration.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
require_relative "invoicing/lib/invoicing"
1010
require_relative "taxes/lib/taxes"
1111
require_relative "fulfillment/lib/fulfillment"
12+
require_relative "communication/lib/communication"
13+
require_relative "processes/lib/processes"
1214

1315
module Ecommerce
1416
class Configuration
@@ -37,6 +39,7 @@ def configure_bounded_contexts(event_store, command_bus)
3739
Taxes::Configuration.new,
3840
ProductCatalog::Configuration.new,
3941
Fulfillment::Configuration.new(@number_generator),
42+
Communication::Configuration.new,
4043
].each { |c| c.call(event_store, command_bus) }
4144
end
4245
end

rails_application/app/processes/processes/welcome_message_process.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ def initialize(event_store, command_bus)
88
def call(event)
99
case event
1010
when Crm::CustomerRegistered
11-
ClientInbox::Message.create(client_uid: event.data.fetch(:customer_id), title: "Welcome to our platform!")
11+
@command_bus.call(
12+
Communication::SendMessage.new(
13+
message_id: SecureRandom.uuid,
14+
receiver_id: event.data.fetch(:customer_id),
15+
message: "Welcome to our platform!")
16+
)
1217
end
1318
end
1419
end

0 commit comments

Comments
 (0)