nexia_event_store 0.9.1 → 0.10.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/lib/event_store/snapshot.rb +45 -14
- data/lib/event_store/version.rb +1 -1
- data/spec/event_store/snapshot_spec.rb +64 -20
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2dba3805be9987a863b9c80cad063ff5ce6ecd2
|
4
|
+
data.tar.gz: 735780ad87bad4795370e51bcf22b71f85184e51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b3aac7d78671e3b9ffd7c136d88ebded20358121fdf9759762cdd846e697325972725e1183a570412e475fe7fbed5bc3fd9768e885037efb1cf848e122f9ad5
|
7
|
+
data.tar.gz: 4da1989af164abf4802e5e963491fd68a2da8993154f568107ed8e02d0e8f1e88b4a576371032ee787c16906151a89fa0fabef2e3d94286c69c9d21343d79ddd
|
data/lib/event_store/snapshot.rb
CHANGED
@@ -41,12 +41,7 @@ module EventStore
|
|
41
41
|
|
42
42
|
t = Time.now
|
43
43
|
result_hash = events_hash.inject([]) do |snapshot, (key, value)|
|
44
|
-
|
45
|
-
raw_event = value.split(EventStore::SNAPSHOT_DELIMITER)
|
46
|
-
event_id = raw_event.first.to_i
|
47
|
-
serialized_event = EventStore.unescape_bytea(raw_event[1])
|
48
|
-
occurred_at = Time.parse(raw_event.last)
|
49
|
-
snapshot + [SerializedEvent.new(fully_qualified_name, serialized_event, event_id, occurred_at)]
|
44
|
+
snapshot + [serialized_event_from_snapshot_event(key, value)]
|
50
45
|
end
|
51
46
|
logger.debug { "#{self.class.name} serializing events took #{Time.now - t} seconds" }
|
52
47
|
result_hash.sort_by(&:event_id).each { |e| yield e }
|
@@ -99,16 +94,47 @@ module EventStore
|
|
99
94
|
end
|
100
95
|
|
101
96
|
def update_fqns!(logger = default_logger)
|
102
|
-
|
97
|
+
logger.debug { "Replacing FQNs in snapshot events" }
|
98
|
+
updated_events = replace_fqns_in_snapshot_hash(read_with_rebuild(logger)) { |fqn| yield fqn }
|
99
|
+
|
100
|
+
logger.debug { "Replacing FQNs in snapshot event ids" }
|
103
101
|
updated_event_ids = replace_fqns_in_snapshot_hash(current_event_id_numbers) { |fqn|
|
104
102
|
fqn == 'current_event_id' ? fqn : (yield fqn)
|
105
103
|
}
|
106
104
|
|
107
|
-
|
105
|
+
logger.debug "Updating snapshot tables in redis"
|
106
|
+
replace_snapshot_tables(updated_event_ids, updated_events)
|
107
|
+
end
|
108
|
+
|
109
|
+
def reject!(logger = default_logger)
|
110
|
+
events_to_keep = read_with_rebuild(logger)
|
111
|
+
event_ids = current_event_id_numbers
|
112
|
+
|
113
|
+
events_to_keep.dup.each { |snapshot_key, snapshot_event|
|
114
|
+
serialized_event = serialized_event_from_snapshot_event(snapshot_key, snapshot_event)
|
115
|
+
drop_it = yield serialized_event
|
116
|
+
|
117
|
+
if drop_it
|
118
|
+
events_to_keep.delete(snapshot_key)
|
119
|
+
event_ids.delete(snapshot_key)
|
120
|
+
end
|
121
|
+
}
|
122
|
+
|
123
|
+
replace_snapshot_tables(event_ids.flatten, events_to_keep.flatten)
|
108
124
|
end
|
109
125
|
|
110
126
|
private
|
111
127
|
|
128
|
+
def serialized_event_from_snapshot_event(snapshot_key, snapshot_value)
|
129
|
+
fully_qualified_name, _ = snapshot_key.split(EventStore::SNAPSHOT_KEY_DELIMITER)
|
130
|
+
raw_event = snapshot_value.split(EventStore::SNAPSHOT_DELIMITER)
|
131
|
+
event_id = raw_event.first.to_i
|
132
|
+
serialized_event = EventStore.unescape_bytea(raw_event[1])
|
133
|
+
occurred_at = Time.parse(raw_event.last)
|
134
|
+
|
135
|
+
SerializedEvent.new(fully_qualified_name, serialized_event, event_id, occurred_at)
|
136
|
+
end
|
137
|
+
|
112
138
|
def replace_fqns_in_snapshot_hash(snapshot_keyed_hash)
|
113
139
|
snapshot_keyed_hash.inject([]) { |memo, (snapshot_key, value)|
|
114
140
|
new_key = replace_fqn_in_snapshot_key(snapshot_key) { |fqn| yield fqn }
|
@@ -122,16 +148,21 @@ module EventStore
|
|
122
148
|
[new_fqn, sub_key].compact.join(EventStore::SNAPSHOT_KEY_DELIMITER)
|
123
149
|
end
|
124
150
|
|
125
|
-
|
126
|
-
def update_snapshot_tables(event_ids_array, events_array, replace: false)
|
151
|
+
def replace_snapshot_tables(event_ids_array, events_array)
|
127
152
|
@redis.multi do
|
128
|
-
|
129
|
-
|
130
|
-
@redis.del snapshot_table if replace
|
131
|
-
@redis.hmset(snapshot_table, events_array)
|
153
|
+
delete_snapshot!
|
154
|
+
update_snapshot_tables(event_ids_array, events_array)
|
132
155
|
end
|
133
156
|
end
|
134
157
|
|
158
|
+
# params are flattened hashes, i.e., [key1, val1, key2, val2, ...]
|
159
|
+
def update_snapshot_tables(event_ids_array, events_array)
|
160
|
+
return unless events_array.any?
|
161
|
+
|
162
|
+
@redis.hmset(snapshot_event_id_table, event_ids_array)
|
163
|
+
@redis.hmset(snapshot_table, events_array)
|
164
|
+
end
|
165
|
+
|
135
166
|
def default_logger
|
136
167
|
Logger.new('/dev/null')
|
137
168
|
end
|
data/lib/event_store/version.rb
CHANGED
@@ -23,66 +23,110 @@ module EventStore
|
|
23
23
|
end
|
24
24
|
|
25
25
|
context "with events in the stream" do
|
26
|
-
let(:client)
|
26
|
+
let(:client) { EventStore::Client.new(AGGREGATE_ID_TWO) }
|
27
|
+
let(:snapshot) { client.snapshot }
|
28
|
+
let(:events) { events_for(AGGREGATE_ID_TWO) }
|
27
29
|
|
28
|
-
before
|
29
|
-
expect(
|
30
|
-
client.append
|
31
|
-
|
30
|
+
before {
|
31
|
+
expect(snapshot.count).to eq(0)
|
32
|
+
client.append events
|
33
|
+
}
|
32
34
|
|
33
35
|
describe "#count" do
|
34
36
|
it "delegates to the snapshot hash" do
|
35
|
-
expect(
|
37
|
+
expect(snapshot.count).to eq(8)
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
41
|
describe "#update_fqns!" do
|
40
|
-
let(:original_events) {
|
42
|
+
let(:original_events) { snapshot.to_a }
|
41
43
|
|
42
44
|
it "replaces fully qualified names in the snapshot with the value of a block" do
|
43
|
-
|
45
|
+
snapshot.update_fqns! { |fqn|
|
44
46
|
fqn =~ /^(e[0-9])/ ? fqn.upcase : fqn
|
45
47
|
}
|
46
48
|
|
47
49
|
expected_snapshot_events = original_events.map { |serialized_event| serialized_event.fully_qualified_name.upcase }
|
48
|
-
expect(
|
50
|
+
expect(snapshot.map(&:fully_qualified_name).to_set).to eq(expected_snapshot_events.to_set)
|
49
51
|
end
|
50
52
|
|
51
53
|
it "does not affect the current event id" do
|
52
|
-
old_event_id =
|
54
|
+
old_event_id = snapshot.event_id
|
53
55
|
|
54
|
-
|
56
|
+
snapshot.update_fqns! { |fqn| fqn.upcase }
|
55
57
|
|
56
|
-
new_event_id =
|
58
|
+
new_event_id = snapshot.event_id
|
57
59
|
|
58
60
|
expect(new_event_id).to eq(old_event_id)
|
59
61
|
end
|
60
62
|
|
61
63
|
it "doesn't affect the fully qualified name when the block returns nil" do
|
62
64
|
old_fqns = original_events.map(&:fully_qualified_name)
|
63
|
-
|
65
|
+
snapshot.update_fqns! { |_fqn| nil }
|
66
|
+
|
67
|
+
expect(snapshot.map(&:fully_qualified_name).to_set).to eq(old_fqns.to_set)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#reject!" do
|
72
|
+
it "yields the serialized event to the block" do
|
73
|
+
snapshot.reject! { |serialized_event|
|
74
|
+
expect(events.map(&:fully_qualified_name)).to include(serialized_event.fully_qualified_name)
|
75
|
+
expect(events.map(&:serialized_event)).to include(serialized_event.serialized_event)
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when the block returns true" do
|
80
|
+
before(:each) { snapshot.reject! { |serialized_event| serialized_event.fully_qualified_name == 'e1' } }
|
81
|
+
|
82
|
+
it "removes the event from the snapshot" do
|
83
|
+
expect(snapshot.map(&:fully_qualified_name)).not_to include('e1')
|
84
|
+
end
|
85
|
+
|
86
|
+
it "removes the event id from the snapshot" do
|
87
|
+
expect(snapshot.event_id_for('e1')).to eq(-1)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context "when the block returns false" do
|
92
|
+
before(:each) { snapshot.reject! { |serialized_event| serialized_event.fully_qualified_name != 'e1' } }
|
93
|
+
|
94
|
+
it "retains the event in the snapshot" do
|
95
|
+
expect(snapshot.map(&:fully_qualified_name)).to include('e1')
|
96
|
+
end
|
97
|
+
|
98
|
+
it "retains the event id in the snapshot" do
|
99
|
+
expect(snapshot.event_id_for('e1')).not_to eq(-1)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when all events are rejected" do
|
104
|
+
before(:each) { snapshot.reject! { true } }
|
64
105
|
|
65
|
-
|
106
|
+
it "deletes the snapshot out of Redis" do
|
107
|
+
expect(EventStore.redis.keys(snapshot.snapshot_table).length).to eq(0)
|
108
|
+
expect(EventStore.redis.keys(snapshot.snapshot_event_id_table).length).to eq(0)
|
109
|
+
end
|
66
110
|
end
|
67
111
|
end
|
68
112
|
|
69
113
|
it "rebuilds a snapshot after it is deleted" do
|
70
|
-
snapshot =
|
114
|
+
snapshot = snapshot
|
71
115
|
client.delete_snapshot!
|
72
116
|
client.rebuild_snapshot!
|
73
|
-
expect(
|
117
|
+
expect(snapshot).to eq(snapshot)
|
74
118
|
end
|
75
119
|
|
76
120
|
it "automatically rebuilds the snapshot if events exist, but the snapshot is empty" do
|
77
|
-
snapshot =
|
121
|
+
snapshot = snapshot
|
78
122
|
client.delete_snapshot!
|
79
|
-
expect(
|
123
|
+
expect(snapshot).to eq(snapshot)
|
80
124
|
end
|
81
125
|
|
82
126
|
it "finds the most recent records for each type" do
|
83
127
|
expected_snapshot_events = %w{e3 e1 e2 e5 e4 e7 e8 e7} #sorted by version no
|
84
128
|
expected_snapshot = serialized_events(expected_snapshot_events)
|
85
|
-
actual_snapshot =
|
129
|
+
actual_snapshot = snapshot
|
86
130
|
|
87
131
|
expect(client.event_stream.count).to eq(15)
|
88
132
|
expect(actual_snapshot.map(&:fully_qualified_name)).to eq(expected_snapshot_events)
|
@@ -91,7 +135,7 @@ module EventStore
|
|
91
135
|
end
|
92
136
|
|
93
137
|
it "increments the version number of the snapshot when an event is appended" do
|
94
|
-
expect(
|
138
|
+
expect(snapshot.event_id).to eq(client.raw_event_stream.last[:id])
|
95
139
|
end
|
96
140
|
end
|
97
141
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexia_event_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Saieg, John Colvin
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-03-
|
12
|
+
date: 2016-03-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|