sandthorn_driver_sequel 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/sandthorn_driver_sequel/access/event_access.rb +2 -2
- data/lib/sandthorn_driver_sequel/version.rb +1 -1
- data/spec/asking_for_aggregates_to_snapshot_spec.rb +48 -48
- data/spec/driver_interface_spec.rb +5 -5
- data/spec/event_store_with_context_spec.rb +22 -22
- data/spec/get_events_spec.rb +120 -120
- data/spec/migration_specifying_domain_spec.rb +31 -31
- data/spec/saving_events_spec.rb +94 -65
- data/spec/saving_snapshot_spec.rb +70 -70
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b8be400a63faf0cff694bfed4677cad95df61e2
|
4
|
+
data.tar.gz: 3ded4bab8764c6534f4580e16e78c6886f66f7f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 955a9fc22846b2ec3e4a3091dd57a9b1e5b3a4bf16f740e81e4b8e3c5e27848c088b8511a72aba01e8765c91d9c811cdfa04a757cbe939c7d3811405aa2ba85a
|
7
|
+
data.tar.gz: b4149f981b2ac7b5a504ba8a55824ef55c9f88a239ffb37d703173387996fc5288ca124f6c7cfb6a15d63a3f71de762895ec0d499ee16958ed4fd2211c2064ce
|
data/Rakefile
CHANGED
@@ -54,7 +54,7 @@ module SandthornDriverSequel
|
|
54
54
|
def build_event_data(aggregate, timestamp, event)
|
55
55
|
{
|
56
56
|
aggregate_table_id: aggregate.id,
|
57
|
-
aggregate_version:
|
57
|
+
aggregate_version: aggregate.aggregate_version,
|
58
58
|
event_name: event.event_name,
|
59
59
|
event_data: event.event_data,
|
60
60
|
timestamp: timestamp
|
@@ -73,7 +73,7 @@ module SandthornDriverSequel
|
|
73
73
|
def store_event(aggregate, timestamp, event)
|
74
74
|
event = EventWrapper.new(event)
|
75
75
|
aggregate.aggregate_version += 1
|
76
|
-
check_versions!(aggregate, event)
|
76
|
+
check_versions!(aggregate, event) if event[:aggregate_version]
|
77
77
|
data = build_event_data(aggregate, timestamp, event)
|
78
78
|
storage.events.insert(data)
|
79
79
|
end
|
@@ -5,60 +5,60 @@ class Bar; end
|
|
5
5
|
|
6
6
|
module SandthornDriverSequel
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
describe EventStore do
|
9
|
+
before(:each) { prepare_for_test }
|
10
|
+
context "when asking for aggregates to snapshot" do
|
11
|
+
let(:aggregates) {
|
12
|
+
[{id: "1", class_name: Foo}, {id: "2", class_name: Bar},{id: "3", class_name: Foo}]}
|
13
13
|
|
14
|
-
|
14
|
+
before(:each) {save_test_events}
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
context "when asking for type 'Bar' and max event count 5" do
|
17
|
+
let(:needs_snapshot) { event_store.obsolete_snapshots aggregate_types: [Bar], max_event_distance: 5 }
|
18
|
+
context "and no snapshots exist" do
|
19
|
+
it "should return that id 2 with class Bar need to be snapshotted" do
|
20
|
+
expect(needs_snapshot.length).to eql 1
|
21
|
+
expect(needs_snapshot.first[:aggregate_id]).to eql aggregates[1][:id]
|
22
|
+
expect(needs_snapshot.first[:aggregate_type]).to eql "Bar"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
context "and a recent snapshot exists" do
|
26
|
+
before(:each) do
|
27
27
|
snapshot_data = { event_data: "YO MAN", aggregate_version: 11 }
|
28
28
|
event_store.save_snapshot(snapshot_data, aggregates[1][:id])
|
29
29
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
it "should return nil" do
|
31
|
+
expect(needs_snapshot).to be_empty
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
35
|
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
37
|
+
def save_test_events
|
38
|
+
for_1 = event_generator count: 4, start_at: 1
|
39
|
+
for_2 = event_generator count: 3, start_at: 1
|
40
|
+
for_3 = event_generator count: 6, start_at: 1
|
41
|
+
for_2_2 = event_generator count: 10, start_at: 4
|
42
|
+
for_1_2 = event_generator count: 1, start_at: 5
|
43
|
+
save_events for_1, 0
|
44
|
+
save_events for_2, 1
|
45
|
+
save_events for_3, 2
|
46
|
+
save_events for_1_2, 0
|
47
|
+
save_events for_2_2, 1
|
48
|
+
end
|
49
|
+
def save_events events, aggregate_index
|
50
|
+
event_store.save_events events, aggregates[aggregate_index][:id], aggregates[aggregate_index][:class_name]
|
51
|
+
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
53
|
+
def event_generator count: 1, start_at: 1
|
54
|
+
events = []
|
55
|
+
i = 0
|
56
|
+
while i < count do
|
57
|
+
events << { aggregate_version: i+start_at, event_data: nil, event_name: "event_foo_#{i}" }
|
58
|
+
i += 1
|
59
|
+
end
|
60
|
+
events
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
64
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module SandthornDriverSequel
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
describe EventStore do
|
5
|
+
before(:each) { prepare_for_test }
|
6
|
+
context "interface structure" do
|
7
|
+
let(:subject) { event_store }
|
8
8
|
methods = [
|
9
9
|
:save_events,
|
10
10
|
:save_snapshot,
|
@@ -27,5 +27,5 @@ module SandthornDriverSequel
|
|
27
27
|
end
|
28
28
|
|
29
29
|
end
|
30
|
-
|
30
|
+
end
|
31
31
|
end
|
@@ -1,25 +1,25 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
module SandthornDriverSequel
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
3
|
+
describe EventStore do
|
4
|
+
let(:context) { :event_store_spec }
|
5
|
+
before(:each) { prepare_for_test context: context; prepare_for_test context: nil; }
|
6
|
+
let(:event_store_with_context) { EventStore.new url: event_store_url, context: context }
|
7
|
+
let(:event_store_without_context) { EventStore.new url: event_store_url }
|
8
|
+
context("when saving in one context and retrieving in another") do
|
9
|
+
let(:test_events) do
|
10
|
+
e = []
|
11
|
+
e << {aggregate_version: 1, event_name: "new", event_args: nil, event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
12
|
+
e << {aggregate_version: 2, event_name: "foo", event_args: ["bar"], event_data: "noop"}
|
13
|
+
e << {aggregate_version: 3, event_name: "flubber", event_args: ["bar"] , event_data: "noop"}
|
14
|
+
end
|
15
|
+
let(:aggregate_id) {"c0456e26-e29a-4f67-92fa-130b3a31a39b"}
|
16
|
+
it "should not find them" do
|
17
|
+
event_store_without_context.save_events test_events, aggregate_id, String
|
18
|
+
events = event_store_without_context.get_aggregate_events aggregate_id
|
19
|
+
expect(events.length).to eql test_events.length
|
20
|
+
events_2 = event_store_with_context.get_aggregate_events aggregate_id
|
21
|
+
expect(events_2.length).to eql 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
25
|
end
|
data/spec/get_events_spec.rb
CHANGED
@@ -1,128 +1,128 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module SandthornDriverSequel
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
4
|
+
describe EventStore do
|
5
|
+
before(:each) { prepare_for_test }
|
6
|
+
let(:test_events_a) do
|
7
|
+
e = []
|
8
|
+
e << {aggregate_version: 1, event_name: "new", event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
9
|
+
e << {aggregate_version: 2, event_name: "foo", event_data: "A2"}
|
10
|
+
e << {aggregate_version: 3, event_name: "bard", event_data: "A3"}
|
11
|
+
end
|
12
|
+
let(:aggregate_id_a) {"c0456e26-e29a-4f67-92fa-130b3a31a39a"}
|
13
|
+
let(:test_events_b) do
|
14
|
+
e = []
|
15
|
+
e << {aggregate_version: 1, event_name: "new", event_data: "B1" }
|
16
|
+
e << {aggregate_version: 2, event_name: "foo", event_data: "B2"}
|
17
|
+
e << {aggregate_version: 3, event_name: "bar", event_data: "B3"}
|
18
|
+
end
|
19
|
+
let(:aggregate_id_b) {"c0456e26-1234-4f67-92fa-130b3a31a39a"}
|
20
|
+
let(:test_events_c) do
|
21
|
+
e = []
|
22
|
+
e << {aggregate_version: 1, event_name: "new", event_data: "C1" }
|
23
|
+
end
|
24
|
+
let(:test_events_c_2) do
|
25
|
+
e = []
|
26
|
+
e << {aggregate_version: 2, event_name: "flubber", event_data: "C2" }
|
27
|
+
end
|
28
|
+
let(:aggregate_id_c) {"c0456e26-2345-4f67-92fa-130b3a31a39a"}
|
29
|
+
before(:each) do
|
30
|
+
event_store.save_events test_events_a, aggregate_id_a, SandthornDriverSequel::EventStore
|
31
|
+
event_store.save_events test_events_c, aggregate_id_c, String
|
32
|
+
event_store.save_events test_events_b, aggregate_id_b, SandthornDriverSequel::SequelDriver
|
33
|
+
event_store.save_events test_events_c_2, aggregate_id_c, String
|
34
|
+
end
|
35
35
|
|
36
|
-
|
36
|
+
let(:event) { event_store.get_events(take: 1).first }
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
it "returns events that can be merged" do
|
39
|
+
expect(event).to respond_to(:merge)
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
42
|
+
context "when using get_events" do
|
43
|
+
context "and using take" do
|
44
|
+
let(:events) {event_store.get_events after_sequence_number: 0, take: 2}
|
45
|
+
it "should find 2 events" do
|
46
|
+
expect(events.length).to eql 2
|
47
|
+
end
|
48
|
+
end
|
49
|
+
context "and combining args" do
|
50
|
+
let(:events) do
|
51
|
+
all = event_store.get_events after_sequence_number: 0
|
52
|
+
first_seq_number = all[0][:sequence_number]
|
53
|
+
event_store.get_events after_sequence_number: first_seq_number, take: 100
|
54
|
+
end
|
55
|
+
it "should find 7 events" do
|
56
|
+
expect(events.length).to eql 7
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
context "and getting events for SandthornDriverSequel::EventStore, and String after 0" do
|
61
|
+
let(:events) {event_store.get_events after_sequence_number: 0, aggregate_types: [SandthornDriverSequel::EventStore, String]}
|
62
|
+
it "should find 5 events" do
|
63
|
+
expect(events.length).to eql 5
|
64
|
+
end
|
65
|
+
it "should be in sequence_number order" do
|
66
|
+
check = 0
|
67
|
+
events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
68
|
+
end
|
69
|
+
it "should contain only events for aggregate_id_a and aggregate_id_c" do
|
70
|
+
events.each { |e| expect([aggregate_id_a, aggregate_id_c].include?(e[:aggregate_id])).to be_truthy }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
context "and getting events for SandthornDriverSequel::EventStore after 0" do
|
74
|
+
let(:events) {event_store.get_events after_sequence_number: 0, aggregate_types: [SandthornDriverSequel::EventStore]}
|
75
|
+
it "should find 3 events" do
|
76
|
+
expect(events.length).to eql 3
|
77
|
+
end
|
78
|
+
it "should be in sequence_number order" do
|
79
|
+
check = 0
|
80
|
+
events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
81
|
+
end
|
82
|
+
it "should contain only events for aggregate_id_a" do
|
83
|
+
events.each { |e| expect(e[:aggregate_id]).to eql aggregate_id_a }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
context "when using :get_new_events_after_event_id_matching_classname to get events" do
|
88
|
+
context "and getting events for SandthornDriverSequel::EventStore after 0" do
|
89
|
+
let(:events) {event_store.get_new_events_after_event_id_matching_classname 0, SandthornDriverSequel::EventStore}
|
90
|
+
it "should find 3 events" do
|
91
|
+
expect(events.length).to eql 3
|
92
|
+
end
|
93
|
+
it "should be in sequence_number order" do
|
94
|
+
check = 0
|
95
|
+
events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
96
|
+
end
|
97
|
+
it "should contain only events for aggregate_id_a" do
|
98
|
+
events.each { |e| expect(e[:aggregate_id]).to eql aggregate_id_a }
|
99
|
+
end
|
100
|
+
it "should be able to get events after a sequence number" do
|
101
|
+
new_from = events[1][:sequence_number]
|
102
|
+
ev = event_store.get_new_events_after_event_id_matching_classname new_from, SandthornDriverSequel::EventStore
|
103
|
+
expect(ev.last[:aggregate_version]).to eql 3
|
104
|
+
expect(ev.length).to eql 1
|
105
|
+
end
|
106
|
+
it "should be able to limit the number of results" do
|
107
|
+
ev = event_store.get_new_events_after_event_id_matching_classname 0, SandthornDriverSequel::EventStore, take: 2
|
108
|
+
expect(ev.length).to eql 2
|
109
|
+
expect(ev.last[:aggregate_version]).to eql 2
|
110
|
+
end
|
111
|
+
end
|
112
|
+
context "and getting events for String after 0" do
|
113
|
+
let(:events) {event_store.get_new_events_after_event_id_matching_classname 0, "String"}
|
114
|
+
it "should find 3 events" do
|
115
|
+
expect(events.length).to eql 2
|
116
|
+
end
|
117
|
+
it "should be in sequence_number order" do
|
118
|
+
check = 0
|
119
|
+
events.each { |e| expect(e[:sequence_number]).to be > check; check = e[:sequence_number] }
|
120
|
+
end
|
121
|
+
it "should contain only events for aggregate_id_c" do
|
122
|
+
events.each { |e| expect(e[:aggregate_id]).to eql aggregate_id_c }
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
126
|
|
127
|
-
|
127
|
+
end
|
128
128
|
end
|
@@ -1,35 +1,35 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module SandthornDriverSequel
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
4
|
+
describe Migration do
|
5
|
+
def check_tables context = nil
|
6
|
+
events = :events
|
7
|
+
aggregates = :aggregates
|
8
|
+
snapshots = :snapshots
|
9
|
+
if context
|
10
|
+
events = "#{context}_#{events}".to_sym
|
11
|
+
aggregates = "#{context}_#{aggregates}".to_sym
|
12
|
+
snapshots = "#{context}_#{snapshots}".to_sym
|
13
|
+
end
|
14
|
+
migration.driver.execute do |db|
|
15
|
+
expect(db.table_exists? events).to be_truthy, "expected table :#{events} to exist, but it didn't"
|
16
|
+
expect(db.table_exists? aggregates).to be_truthy, "expected table :#{aggregates} to exist, but it didn't"
|
17
|
+
expect(db.table_exists? snapshots).to be_truthy, "expected table :#{snapshots} to exist, but it didn't"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
let(:migration) { Migration.new url: event_store_url, context: context }
|
21
|
+
before(:each) { migration.migrate! }
|
22
|
+
context "when default (nil) eventstore contex" do
|
23
|
+
let(:context) { nil }
|
24
|
+
it "should create the tables events, aggregates and snapshots" do
|
25
|
+
check_tables
|
26
|
+
end
|
27
|
+
end
|
28
|
+
context "when specifying context" do
|
29
|
+
let(:context) { :another_domain }
|
30
|
+
it "should create the tables events, aggregates and snapshots" do
|
31
|
+
check_tables context
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
35
|
end
|
data/spec/saving_events_spec.rb
CHANGED
@@ -2,89 +2,118 @@ require 'spec_helper'
|
|
2
2
|
require 'msgpack'
|
3
3
|
|
4
4
|
module SandthornDriverSequel
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
describe EventStore do
|
6
|
+
before(:each) { prepare_for_test }
|
7
|
+
context "when saving a prefectly sane event stream" do
|
8
|
+
let(:test_events) do
|
9
|
+
e = []
|
10
|
+
e << {aggregate_version: 1, event_name: "new", event_args: nil, event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
11
|
+
e << {aggregate_version: 2, event_name: "foo", event_args: ["bar"], event_data: "noop"}
|
12
|
+
e << {aggregate_version: 3, event_name: "flubber", event_args: ["bar"] , event_data: "noop"}
|
13
|
+
end
|
14
14
|
|
15
15
|
let(:aggregate_id) { "c0456e26-e29a-4f67-92fa-130b3a31a39a" }
|
16
16
|
|
17
17
|
it "should be able to save and retrieve events on the aggregate" do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
event_store.save_events test_events, aggregate_id, String
|
19
|
+
events = event_store.get_aggregate_events aggregate_id
|
20
|
+
expect(events.length).to eql test_events.length
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should have correct keys when asking for events" do
|
24
|
+
event_store.save_events test_events, aggregate_id, String
|
25
|
+
events = event_store.get_aggregate aggregate_id, String
|
26
|
+
event = events.first
|
27
|
+
expect(event[:event_data]).to eql(test_events.first[:event_data])
|
28
28
|
expect(event[:event_name]).to eql("new")
|
29
29
|
expect(event[:aggregate_id]).to eql aggregate_id
|
30
30
|
expect(event[:aggregate_version]).to eql 1
|
31
31
|
expect(event[:sequence_number]).to be_a(Fixnum)
|
32
32
|
expect(event[:timestamp]).to be_a(Time)
|
33
|
-
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when saving two aggregate types" do
|
37
|
+
let(:test_events_1) do
|
38
|
+
e = []
|
39
|
+
e << {aggregate_version: 1, event_name: "new", event_args: nil, event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
40
|
+
e << {aggregate_version: 2, event_name: "foo", event_args: "bar", event_data: "noop"}
|
41
|
+
e << {aggregate_version: 3, event_name: "flubber", event_args: "bar", event_data: "noop"}
|
42
|
+
end
|
43
|
+
let(:test_events_2) do
|
44
|
+
e = []
|
45
|
+
e << {aggregate_version: 1, event_name: "new", event_args: nil, event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
46
|
+
end
|
47
|
+
let(:aggregate_id_1) {"c0456e26-e29a-4f67-92fa-130b3a31a39a"}
|
48
|
+
let(:aggregate_id_2) {"c0456e26-e92b-4f67-92fa-130b3a31b93b"}
|
49
|
+
let(:aggregate_id_3) {"c0456e26-e92b-1234-92fa-130b3a31b93b"}
|
50
|
+
|
51
|
+
before(:each) do
|
52
|
+
event_store.save_events test_events_1, aggregate_id_1, String
|
53
|
+
event_store.save_events test_events_2, aggregate_id_2, Hash
|
54
|
+
event_store.save_events test_events_2, aggregate_id_3, String
|
55
|
+
end
|
56
|
+
|
57
|
+
it "both types should exist in get_all_typenames in alphabetical order" do
|
58
|
+
names = event_store.get_all_types
|
59
|
+
expect(names.length).to eql 2
|
60
|
+
expect(names.first).to eql "Hash"
|
61
|
+
expect(names.last).to eql "String"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should list the aggregate ids when asking for get_aggregate_list_by_typename" do
|
65
|
+
ids = event_store.get_aggregate_ids(aggregate_type: String)
|
66
|
+
expect(ids.length).to eql 2
|
67
|
+
expect(ids.any? { |e| e == aggregate_id_1 }).to be_truthy
|
68
|
+
expect(ids.any? { |e| e == aggregate_id_3 }).to be_truthy
|
69
|
+
end
|
34
70
|
end
|
35
71
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
let(:test_events_2) do
|
44
|
-
e = []
|
45
|
-
e << {aggregate_version: 1, event_name: "new", event_args: nil, event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
46
|
-
end
|
47
|
-
let(:aggregate_id_1) {"c0456e26-e29a-4f67-92fa-130b3a31a39a"}
|
48
|
-
let(:aggregate_id_2) {"c0456e26-e92b-4f67-92fa-130b3a31b93b"}
|
49
|
-
let(:aggregate_id_3) {"c0456e26-e92b-1234-92fa-130b3a31b93b"}
|
50
|
-
|
51
|
-
before(:each) do
|
52
|
-
event_store.save_events test_events_1, aggregate_id_1, String
|
53
|
-
event_store.save_events test_events_2, aggregate_id_2, Hash
|
54
|
-
event_store.save_events test_events_2, aggregate_id_3, String
|
72
|
+
context "when saving events that are serilized with msgpack" do
|
73
|
+
let(:test_data) { {name: "test", hash: {t: 123}} }
|
74
|
+
let(:test_events) do
|
75
|
+
e = []
|
76
|
+
data = MessagePack.pack(test_data, symbolize_keys: true)
|
77
|
+
e << {aggregate_version: 1, event_name: "new", event_args: nil, event_data: data}
|
55
78
|
end
|
79
|
+
let(:aggregate_id_1) {"c0456e26-e29a-4f67-92fa-130b3a31a39a"}
|
56
80
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
expect(names.last).to eql "String"
|
81
|
+
it "should save and get events that are serialized with msgpack" do
|
82
|
+
event_store.save_events test_events, aggregate_id_1, String
|
83
|
+
events = event_store.get_aggregate aggregate_id_1, String
|
84
|
+
expect(MessagePack.unpack(events.first[:event_data], symbolize_keys: true)).to eql test_data
|
62
85
|
end
|
63
86
|
|
64
|
-
it "should list the aggregate ids when asking for get_aggregate_list_by_typename" do
|
65
|
-
ids = event_store.get_aggregate_ids(aggregate_type: String)
|
66
|
-
expect(ids.length).to eql 2
|
67
|
-
expect(ids.any? { |e| e == aggregate_id_1 }).to be_truthy
|
68
|
-
expect(ids.any? { |e| e == aggregate_id_3 }).to be_truthy
|
69
|
-
end
|
70
87
|
end
|
71
88
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
let(:aggregate_id_1) {"c0456e26-e29a-4f67-92fa-130b3a31a39a"}
|
80
|
-
|
81
|
-
it "should save and get events that are serialized with msgpack" do
|
82
|
-
event_store.save_events test_events, aggregate_id_1, String
|
83
|
-
events = event_store.get_aggregate aggregate_id_1, String
|
84
|
-
expect(MessagePack.unpack(events.first[:event_data], symbolize_keys: true)).to eql test_data
|
89
|
+
context "when saving events that have no aggregate_version" do
|
90
|
+
let(:test_events) do
|
91
|
+
e = []
|
92
|
+
e << {aggregate_version: nil, event_name: "new", event_args: nil, event_data: "---\n:method_name: new\n:method_args: []\n:attribute_deltas:\n- :attribute_name: :@aggregate_id\n :old_value: \n :new_value: 0a74e545-be84-4506-8b0a-73e947856327\n"}
|
93
|
+
e << {aggregate_version: nil, event_name: "foo", event_args: ["bar"], event_data: "noop"}
|
94
|
+
e << {aggregate_version: nil, event_name: "flubber", event_args: ["bar"] , event_data: "noop"}
|
85
95
|
end
|
86
96
|
|
87
|
-
|
97
|
+
let(:aggregate_id) { "c0456e26-e29a-4f67-92fa-130b3a31a39a" }
|
98
|
+
|
99
|
+
it "should be able to save and retrieve events on the aggregate" do
|
100
|
+
event_store.save_events test_events, aggregate_id, String
|
101
|
+
events = event_store.get_aggregate_events aggregate_id
|
102
|
+
expect(events.length).to eql test_events.length
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should have correct keys when asking for events" do
|
106
|
+
event_store.save_events test_events, aggregate_id, String
|
107
|
+
events = event_store.get_aggregate aggregate_id, String
|
108
|
+
event = events.first
|
109
|
+
expect(event[:event_data]).to eql(test_events.first[:event_data])
|
110
|
+
expect(event[:event_name]).to eql("new")
|
111
|
+
expect(event[:aggregate_id]).to eql aggregate_id
|
112
|
+
expect(event[:aggregate_version]).to eql 1
|
113
|
+
expect(event[:sequence_number]).to be_a(Fixnum)
|
114
|
+
expect(event[:timestamp]).to be_a(Time)
|
115
|
+
end
|
116
|
+
end
|
88
117
|
|
89
|
-
|
118
|
+
end
|
90
119
|
end
|
@@ -2,76 +2,76 @@ require 'spec_helper'
|
|
2
2
|
require 'yaml'
|
3
3
|
|
4
4
|
module SandthornDriverSequel
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
5
|
+
describe EventStore do
|
6
|
+
before(:each) { prepare_for_test }
|
7
|
+
let(:aggregate_id) { @id ||= UUIDTools::UUID.random_create.to_s }
|
8
|
+
let(:test_events) { [{aggregate_version: 1, event_data: nil, event_name: "new"},{aggregate_version: 2, event_data: nil, event_name: "foo"}] }
|
9
|
+
let(:additional_events) { [{aggregate_version: 3, event_data: nil, event_name: "klopp"},{aggregate_version: 4, event_data: nil, event_name: "flipp"}] }
|
10
|
+
let(:snapshot_data) { { event_data: YAML.dump(Object.new), aggregate_version: 2 } }
|
11
|
+
let(:save_snapshot) { event_store.save_snapshot snapshot_data, aggregate_id }
|
12
|
+
let(:save_events) { event_store.save_events test_events, aggregate_id, SandthornDriverSequel::EventStore }
|
13
|
+
let(:save_additional_events) { event_store.save_events additional_events, aggregate_id, SandthornDriverSequel::EventStore }
|
14
|
+
context "when loading an aggregate using get_aggregate" do
|
15
|
+
context "and it has a snapshot" do
|
16
|
+
before(:each) do
|
17
|
+
save_events
|
18
|
+
save_snapshot
|
19
|
+
save_additional_events
|
20
|
+
end
|
21
|
+
let(:events) { event_store.get_aggregate aggregate_id, SandthornDriverSequel::EventStore }
|
22
|
+
it "should have the first event as :aggregate_set_from_snapshot" do
|
23
|
+
expect(events.first[:event_name]).to eql "aggregate_set_from_snapshot"
|
24
|
+
end
|
25
|
+
it "should have additional events after first snapshot-event" do
|
26
|
+
expect(events.length).to eql 1+additional_events.length
|
27
|
+
expect(events[1][:aggregate_version]).to eql additional_events[0][:aggregate_version]
|
28
|
+
expect(events.last[:aggregate_version]).to eql additional_events.last[:aggregate_version]
|
29
|
+
end
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
32
|
+
end
|
33
|
+
context "when saving a snapshot" do
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
35
|
+
context "and events are saved beforehand" do
|
36
|
+
before(:each) { save_events }
|
37
|
+
it "should be able to save snapshot" do
|
38
|
+
expect { save_snapshot }.to_not raise_error
|
39
|
+
end
|
40
|
+
it "should be able to save and get snapshot" do
|
41
|
+
save_snapshot
|
42
|
+
snap = event_store.get_snapshot(aggregate_id)
|
43
|
+
expect(snap).to eql snapshot_data
|
44
|
+
end
|
45
|
+
end
|
46
|
+
context "when trying to save a snapshot on a non-existing aggregate" do
|
47
|
+
it "should raise a NonAggregateError" do
|
48
|
+
expect { save_snapshot }.to raise_error SandthornDriverSequel::Errors::NoAggregateError
|
49
|
+
end
|
50
|
+
end
|
51
|
+
context "when trying to save a snapshot with a non-existing aggregate_version" do
|
52
|
+
before(:each) { save_events }
|
53
|
+
it "should raise a WrongAggregateVersion error" do
|
54
|
+
data = snapshot_data
|
55
|
+
data[:aggregate_version] = 100
|
56
|
+
expect { event_store.save_snapshot data, aggregate_id }.to raise_error SandthornDriverSequel::Errors::WrongSnapshotVersionError
|
57
|
+
end
|
58
|
+
end
|
59
|
+
context "when saving a snapshot twice" do
|
60
|
+
before(:each) { save_events; save_snapshot }
|
61
|
+
it "should not raise error" do
|
62
|
+
expect { save_snapshot }.to_not raise_error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
context "when saving a snapshot on a version less than current version" do
|
66
|
+
before(:each) { save_events; }
|
67
|
+
it "should save without protesting" do
|
68
|
+
data = snapshot_data
|
69
|
+
data[:aggregate_version] = 1
|
70
|
+
event_store.save_snapshot(data, aggregate_id)
|
71
|
+
snap = event_store.get_snapshot(aggregate_id)
|
72
|
+
expect(snap).to eql data
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
77
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sandthorn_driver_sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lars Krantz
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2016-01-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
@@ -309,7 +309,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
309
309
|
version: '0'
|
310
310
|
requirements: []
|
311
311
|
rubyforge_project:
|
312
|
-
rubygems_version: 2.4.
|
312
|
+
rubygems_version: 2.4.8
|
313
313
|
signing_key:
|
314
314
|
specification_version: 4
|
315
315
|
summary: Sequel driver for Sandthorn
|