sandthorn_driver_sequel_2 0.0.1
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 +7 -0
- data/.autotest +3 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Guardfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +10 -0
- data/lib/sandthorn_driver_sequel_2/access/event_access.rb +94 -0
- data/lib/sandthorn_driver_sequel_2/access/snapshot_access.rb +88 -0
- data/lib/sandthorn_driver_sequel_2/access.rb +19 -0
- data/lib/sandthorn_driver_sequel_2/errors.rb +49 -0
- data/lib/sandthorn_driver_sequel_2/event_query.rb +68 -0
- data/lib/sandthorn_driver_sequel_2/event_store.rb +138 -0
- data/lib/sandthorn_driver_sequel_2/event_store_context.rb +15 -0
- data/lib/sandthorn_driver_sequel_2/file_output_wrappers/events.rb +37 -0
- data/lib/sandthorn_driver_sequel_2/migration.rb +81 -0
- data/lib/sandthorn_driver_sequel_2/sequel_driver.rb +23 -0
- data/lib/sandthorn_driver_sequel_2/storage.rb +43 -0
- data/lib/sandthorn_driver_sequel_2/utilities/array.rb +13 -0
- data/lib/sandthorn_driver_sequel_2/utilities.rb +1 -0
- data/lib/sandthorn_driver_sequel_2/version.rb +3 -0
- data/lib/sandthorn_driver_sequel_2/wrappers/event_wrapper.rb +12 -0
- data/lib/sandthorn_driver_sequel_2/wrappers/snapshot_wrapper.rb +11 -0
- data/lib/sandthorn_driver_sequel_2/wrappers.rb +2 -0
- data/lib/sandthorn_driver_sequel_2.rb +24 -0
- data/sandthorn_driver_sequel_2.gemspec +41 -0
- data/spec/asking_for_aggregates_to_snapshot_spec.rb +64 -0
- data/spec/benchmark_spec.rb +125 -0
- data/spec/db/.keep +0 -0
- data/spec/driver_interface_spec.rb +31 -0
- data/spec/event_access_spec.rb +100 -0
- data/spec/event_store_file_output_spec.rb +44 -0
- data/spec/event_store_with_context_spec.rb +25 -0
- data/spec/get_events_spec.rb +128 -0
- data/spec/migration_specifying_domain_spec.rb +32 -0
- data/spec/saving_events_spec.rb +90 -0
- data/spec/saving_snapshot_spec.rb +77 -0
- data/spec/snapshot_access_spec.rb +125 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/storage_spec.rb +66 -0
- data/spec/storage_to_file_spec.rb +53 -0
- metadata +334 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SandthornDriverSequel2
|
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, SandthornDriverSequel2::EventStore
|
31
|
+
event_store.save_events test_events_c, aggregate_id_c, String
|
32
|
+
event_store.save_events test_events_b, aggregate_id_b, SandthornDriverSequel2::SequelDriver
|
33
|
+
event_store.save_events test_events_c_2, aggregate_id_c, String
|
34
|
+
end
|
35
|
+
|
36
|
+
let(:event) { event_store.get_events(take: 1).first }
|
37
|
+
|
38
|
+
it "returns events that can be merged" do
|
39
|
+
expect(event).to respond_to(:merge)
|
40
|
+
end
|
41
|
+
|
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 SandthornDriverSequel2::EventStore, and String after 0" do
|
61
|
+
let(:events) {event_store.get_events after_sequence_number: 0, aggregate_types: [SandthornDriverSequel2::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 SandthornDriverSequel2::EventStore after 0" do
|
74
|
+
let(:events) {event_store.get_events after_sequence_number: 0, aggregate_types: [SandthornDriverSequel2::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 SandthornDriverSequel2::EventStore after 0" do
|
89
|
+
let(:events) {event_store.get_new_events_after_event_id_matching_classname 0, SandthornDriverSequel2::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, SandthornDriverSequel2::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, SandthornDriverSequel2::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
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SandthornDriverSequel2
|
4
|
+
describe Migration do
|
5
|
+
def check_tables context = nil
|
6
|
+
events = :events
|
7
|
+
snapshots = :snapshots
|
8
|
+
if context
|
9
|
+
events = "#{context}_#{events}".to_sym
|
10
|
+
snapshots = "#{context}_#{snapshots}".to_sym
|
11
|
+
end
|
12
|
+
migration.driver.execute do |db|
|
13
|
+
expect(db.table_exists? events).to be_truthy, "expected table :#{events} to exist, but it didn't"
|
14
|
+
expect(db.table_exists? snapshots).to be_truthy, "expected table :#{snapshots} to exist, but it didn't"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
let(:migration) { Migration.new url: event_store_url, context: context }
|
18
|
+
before(:each) { migration.migrate! }
|
19
|
+
context "when default (nil) eventstore contex" do
|
20
|
+
let(:context) { nil }
|
21
|
+
it "should create the tables events, aggregates and snapshots" do
|
22
|
+
check_tables
|
23
|
+
end
|
24
|
+
end
|
25
|
+
context "when specifying context" do
|
26
|
+
let(:context) { :another_domain }
|
27
|
+
it "should create the tables events, aggregates and snapshots" do
|
28
|
+
check_tables context
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'msgpack'
|
3
|
+
|
4
|
+
module SandthornDriverSequel2
|
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
|
+
|
15
|
+
let(:aggregate_id) { "c0456e26-e29a-4f67-92fa-130b3a31a39a" }
|
16
|
+
|
17
|
+
it "should be able to save and retrieve events on the aggregate" do
|
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
|
+
expect(event[:event_name]).to eql("new")
|
29
|
+
expect(event[:aggregate_id]).to eql aggregate_id
|
30
|
+
expect(event[:aggregate_version]).to eql 1
|
31
|
+
expect(event[:sequence_number]).to be_a(Fixnum)
|
32
|
+
expect(event[:timestamp]).to be_a(Time)
|
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
|
70
|
+
end
|
71
|
+
|
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}
|
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
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# require 'spec_helper'
|
2
|
+
# require 'yaml'
|
3
|
+
|
4
|
+
# module SandthornDriverSequel2
|
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, SandthornDriverSequel2::EventStore }
|
13
|
+
# let(:save_additional_events) { event_store.save_events additional_events, aggregate_id, SandthornDriverSequel2::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, SandthornDriverSequel2::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
|
+
|
32
|
+
# end
|
33
|
+
# context "when saving a snapshot" do
|
34
|
+
|
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 SandthornDriverSequel2::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 SandthornDriverSequel2::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
|
+
# end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# require 'spec_helper'
|
2
|
+
|
3
|
+
# module SandthornDriverSequel2
|
4
|
+
# describe SnapshotAccess do
|
5
|
+
# include EventStoreContext
|
6
|
+
|
7
|
+
# before do
|
8
|
+
# prepare_for_test
|
9
|
+
# end
|
10
|
+
|
11
|
+
# let(:context) { :test }
|
12
|
+
# let(:db) { Sequel.connect(event_store_url)}
|
13
|
+
# let(:aggregate_id) { generate_uuid }
|
14
|
+
# let(:storage) { Storage.new(db, :test) }
|
15
|
+
# let(:aggregate_access) { AggregateAccess.new(storage) }
|
16
|
+
# let(:event_access) { EventAccess.new(storage) }
|
17
|
+
# let(:aggregate) { aggregate_access.register_aggregate(aggregate_id, "foo") }
|
18
|
+
# let(:access) { SnapshotAccess.new(storage) }
|
19
|
+
# let(:events) do
|
20
|
+
# [
|
21
|
+
# {
|
22
|
+
# aggregate_id: aggregate_id,
|
23
|
+
# aggregate_type: "Foo",
|
24
|
+
# aggregate_version: 1,
|
25
|
+
# event_name: "new",
|
26
|
+
# event_data: "new_data"
|
27
|
+
# },{
|
28
|
+
# aggregate_id: aggregate_id,
|
29
|
+
# aggregate_type: "Foo",
|
30
|
+
# aggregate_version: 2,
|
31
|
+
# event_name: "foo",
|
32
|
+
# event_data: "foo_data"
|
33
|
+
# }
|
34
|
+
# ]
|
35
|
+
# end
|
36
|
+
|
37
|
+
# describe "#find_by_aggregate_id" do
|
38
|
+
# it "returns the correct data" do
|
39
|
+
# aggregate = aggregate_access.register_aggregate(aggregate_id, "foo")
|
40
|
+
# access.record_snapshot(aggregate.aggregate_id, { aggregate_version: 0, event_data: "data" })
|
41
|
+
# aggregate.update(aggregate_version: 1)
|
42
|
+
# snapshot = access.find_by_aggregate_id(aggregate.aggregate_id)
|
43
|
+
# expected = {
|
44
|
+
# # aggregate_table_id: aggregate.id,
|
45
|
+
# aggregate_id: aggregate.aggregate_id,
|
46
|
+
# aggregate_type: "Foo",
|
47
|
+
# aggregate_version: 0,
|
48
|
+
# snapshot_data: "data",
|
49
|
+
# id: snapshot.id
|
50
|
+
# }
|
51
|
+
# expect(snapshot.values).to eq(expected)
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
|
55
|
+
# describe "#record" do
|
56
|
+
# context "when the aggregate doesn't exist" do
|
57
|
+
# it "raises an error" do
|
58
|
+
# expect { access.record_snapshot("qux", "data") }.to raise_error(Errors::NoAggregateError)
|
59
|
+
# end
|
60
|
+
# end
|
61
|
+
# context "when the aggregate exists" do
|
62
|
+
# context "when no previous snapshot exists" do
|
63
|
+
# it "records the snapshot" do
|
64
|
+
# #aggregate_table_id = aggregate_access.register_aggregate(aggregate_id, "foo").id
|
65
|
+
# expect(access.find_by_aggregate_id(aggregate_id)).to be_nil
|
66
|
+
# access.record_snapshot(aggregate_id, { aggregate_version: 0, event_data: "data"})
|
67
|
+
|
68
|
+
# snapshot = access.find_by_aggregate_id(aggregate_id)
|
69
|
+
# expect(snapshot).to_not be_nil
|
70
|
+
# expect(snapshot.aggregate_id).to eq(aggregate_id)
|
71
|
+
# expect(snapshot.snapshot_data).to eq("data")
|
72
|
+
# expect(snapshot.aggregate_version).to eq(0)
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
# context "when the snapshot isn't fresh" do
|
76
|
+
# context "when the versions match" do
|
77
|
+
# it "records a new snapshot" do
|
78
|
+
# #aggregate = aggregate_access.register_aggregate(aggregate_id, "foo")
|
79
|
+
# expect(access.find_by_aggregate_id(aggregate_id)).to be_nil
|
80
|
+
# access.record_snapshot(aggregate_id, { aggregate_version: 0, aggregate_type: "Foo", event_data: "data"})
|
81
|
+
# event_access.store_events(events)
|
82
|
+
# access.record_snapshot(aggregate_id, { aggregate_version: 2, aggregate_type: "Foo", event_data: "other_data"})
|
83
|
+
|
84
|
+
# snapshot = access.find_by_aggregate_id(aggregate_id)
|
85
|
+
# expect(snapshot).to_not be_nil
|
86
|
+
# expect(snapshot.aggregate_id).to eq(aggregate_id)
|
87
|
+
# expect(snapshot.snapshot_data).to eq("other_data")
|
88
|
+
# expect(snapshot.aggregate_version).to eq(2)
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
|
92
|
+
# # context "when the versions don't match" do
|
93
|
+
# # it "raises an error" do
|
94
|
+
# # aggregate = aggregate_access.register_aggregate(aggregate_id, "foo")
|
95
|
+
# # aggregate.update(aggregate_version: 10)
|
96
|
+
# # expect { access.record_snapshot(aggregate_id, snapshot_data) }.to raise_error
|
97
|
+
# # end
|
98
|
+
# # end
|
99
|
+
# end
|
100
|
+
# context "when the snapshot is fresh" do
|
101
|
+
# it "doesn't record a snapshot" do
|
102
|
+
# aggregate = aggregate_access.register_aggregate(aggregate_id, "foo")
|
103
|
+
# expect(access.find_by_aggregate_id(aggregate_id)).to be_nil
|
104
|
+
# access.record_snapshot(aggregate_id, { aggregate_version: 0, event_data: "data"})
|
105
|
+
# access.record_snapshot(aggregate_id, { aggregate_version: 0, event_data: "new_data"})
|
106
|
+
# snapshot = access.find_by_aggregate_id(aggregate_id)
|
107
|
+
# expect(snapshot.snapshot_data).to eq("data")
|
108
|
+
# end
|
109
|
+
# end
|
110
|
+
# end
|
111
|
+
# end
|
112
|
+
|
113
|
+
# it "can write and read snapshots" do
|
114
|
+
# snapshot_id = access.record_snapshot(aggregate.aggregate_id, { aggregate_version: 0, event_data: "data" })
|
115
|
+
# snapshot = access.find(snapshot_id)
|
116
|
+
# expect(snapshot).to_not be_nil
|
117
|
+
# expect(snapshot.snapshot_data).to eq("data")
|
118
|
+
# expect(snapshot)
|
119
|
+
# end
|
120
|
+
|
121
|
+
# def generate_uuid
|
122
|
+
# SecureRandom.uuid
|
123
|
+
# end
|
124
|
+
# end
|
125
|
+
# end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'sandthorn_driver_sequel_2'
|
2
|
+
require 'sandthorn_driver_sequel_2/migration'
|
3
|
+
require 'ap'
|
4
|
+
require 'uuidtools'
|
5
|
+
|
6
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
7
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
8
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
9
|
+
# loaded once.
|
10
|
+
#
|
11
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.run_all_when_everything_filtered = true
|
14
|
+
config.filter_run :focus
|
15
|
+
config.filter_run_excluding benchmark: true
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
18
|
+
def prepare_for_test context: :test
|
19
|
+
migrator = SandthornDriverSequel2::Migration.new url: event_store_url, context: context
|
20
|
+
migrator.migrate!
|
21
|
+
migrator.send(:clear_for_test)
|
22
|
+
end
|
23
|
+
|
24
|
+
def event_store_url
|
25
|
+
"sqlite://spec/db/event_store.sqlite3"
|
26
|
+
#"postgres://morganhallgren@localhost:5432/test_1"
|
27
|
+
end
|
28
|
+
|
29
|
+
def event_store context: :test
|
30
|
+
SandthornDriverSequel2::EventStore.new url: event_store_url, context: context
|
31
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SandthornDriverSequel2
|
4
|
+
|
5
|
+
describe Storage do
|
6
|
+
let(:context) { :test }
|
7
|
+
before do
|
8
|
+
prepare_for_test(context: context)
|
9
|
+
end
|
10
|
+
let(:db) { Sequel.connect(event_store_url) }
|
11
|
+
let(:driver) { SequelDriver.new(event_store_url)}
|
12
|
+
let(:storage) { Storage.new(db, context, nil) }
|
13
|
+
|
14
|
+
# describe "anonymous aggegrate class" do
|
15
|
+
# it "can insert and read data" do
|
16
|
+
# create_aggregate
|
17
|
+
# aggregate = storage.aggregates.first(aggregate_id: "foo", aggregate_type: "Foo")
|
18
|
+
# expect(aggregate).to_not be_nil
|
19
|
+
# end
|
20
|
+
|
21
|
+
# it "can update data" do
|
22
|
+
# create_aggregate
|
23
|
+
# storage.aggregates.where(aggregate_id: "foo").update(aggregate_version: 2)
|
24
|
+
# aggregate = storage.aggregates.first(aggregate_id: "foo")
|
25
|
+
# expect(aggregate.aggregate_version).to eq(2)
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
|
29
|
+
describe "anonymous event class" do
|
30
|
+
it "can insert and read data" do
|
31
|
+
data, event_id = create_event
|
32
|
+
event = storage.events.first(sequence_number: event_id).values
|
33
|
+
expected = data.merge(sequence_number: event_id)
|
34
|
+
expected_time = expected.delete(:timestamp)
|
35
|
+
actual_time = event.delete(:timestamp)
|
36
|
+
expect(event).to eq(expected)
|
37
|
+
expect(actual_time.to_i).to eq(actual_time.to_i)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "can update data" do
|
41
|
+
data, event_id = create_event
|
42
|
+
storage.events.where(sequence_number: event_id).update(event_name: "qux")
|
43
|
+
event = storage.events.first(sequence_number: event_id)
|
44
|
+
expect(event.event_name).to eq("qux")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# def create_aggregate
|
49
|
+
# storage.aggregates.insert(aggregate_id: "foo", aggregate_type: "Foo")
|
50
|
+
# end
|
51
|
+
|
52
|
+
def create_event
|
53
|
+
data = {
|
54
|
+
aggregate_id: "foo",
|
55
|
+
aggregate_version: 1,
|
56
|
+
aggregate_type: "Foo",
|
57
|
+
event_name: "foo",
|
58
|
+
event_data: "bar",
|
59
|
+
timestamp: Time.now.utc
|
60
|
+
}
|
61
|
+
event_id = storage.events.insert(data)
|
62
|
+
return data, event_id
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SandthornDriverSequel2
|
4
|
+
|
5
|
+
describe Storage do
|
6
|
+
|
7
|
+
context "ToFile" do
|
8
|
+
|
9
|
+
let(:context) { :test }
|
10
|
+
let(:event_file) { "spec/db_file/events.csv" }
|
11
|
+
|
12
|
+
before do
|
13
|
+
prepare_for_test(context: context)
|
14
|
+
end
|
15
|
+
after(:each) do
|
16
|
+
File.delete(event_file)
|
17
|
+
end
|
18
|
+
let(:db) { Sequel.connect(event_store_url) }
|
19
|
+
let(:driver) { SequelDriver.new(event_store_url)}
|
20
|
+
let(:storage) { Storage.new(db, context, event_file) }
|
21
|
+
|
22
|
+
describe "anonymous event class" do
|
23
|
+
it "insert no data to the db" do
|
24
|
+
data, event_id = create_event
|
25
|
+
event = storage.events.first
|
26
|
+
|
27
|
+
expect(event).to be_nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "can read data from file" do
|
31
|
+
data, event_id = create_event
|
32
|
+
file = File.open event_file
|
33
|
+
expect(file.first).to eq("1;foo;1;Foo;foo;bar;#{data[:timestamp]}\n")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_event
|
38
|
+
data = {
|
39
|
+
aggregate_id: "foo",
|
40
|
+
aggregate_version: 1,
|
41
|
+
aggregate_type: "Foo",
|
42
|
+
event_name: "foo",
|
43
|
+
event_data: "bar",
|
44
|
+
timestamp: Time.now.utc
|
45
|
+
}
|
46
|
+
event_id = storage.events.insert(data)
|
47
|
+
storage.events.flush
|
48
|
+
return data, event_id
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|