sandthorn_driver_sequel_2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|