nexia_event_store 0.6.1 → 0.7.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/db/database.yml +2 -2
- data/db/pg_migrations/003_add_agg_id_occurred_fqn_idx_to_event_store.rb +10 -0
- data/db/pg_migrations/004_add_fqn_lookup_table_to_event_store.rb +68 -0
- data/lib/event_store/event_stream.rb +34 -12
- data/lib/event_store/version.rb +1 -1
- data/lib/event_store.rb +8 -0
- data/spec/event_store/client_spec.rb +5 -5
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 810f954e899ec5777b6f4b57431d9739734f8519
|
4
|
+
data.tar.gz: b0fc4fae467b95e007d317894206618d9ada5899
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74d45ebf5fe97fdb52e067b17885be10159e2a94200671b1fa106a75e90e6428e33a362ded5a481c92d762981c5e9cba56f60126960bc34216845ccea3306045
|
7
|
+
data.tar.gz: 58ed1ef36e12724c2ee1ea689af1eeb3d85164677c800aadac21a2ac11b20d92b09e590a05162595b1f44cc35afb2c2d95b71dacd2689e5dd3ed1c7587e60170
|
data/db/database.yml
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'event_store'
|
2
|
+
Sequel.migration do
|
3
|
+
no_transaction
|
4
|
+
change do
|
5
|
+
idx_name = "#{EventStore.schema}_#{EventStore.table_name}_aggregate_id_occurred_at_name_idx"
|
6
|
+
alter_table((EventStore.schema + "__" + EventStore.table_name).to_sym) do
|
7
|
+
add_index([:aggregate_id, :occurred_at, :fully_qualified_name], name: idx_name, concurrently: true)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'event_store'
|
2
|
+
Sequel.migration do
|
3
|
+
no_transaction
|
4
|
+
|
5
|
+
event_store_table = (EventStore.schema + "__" + EventStore.table_name).to_sym
|
6
|
+
lookup_table = (EventStore.schema + "__" + EventStore.lookup_table_name).to_sym
|
7
|
+
|
8
|
+
event_store_table_name = event_store_table.to_s.gsub(/__/, '.')
|
9
|
+
lookup_table_name = lookup_table.to_s.gsub(/__/, '.')
|
10
|
+
|
11
|
+
up do
|
12
|
+
create_table(lookup_table) do
|
13
|
+
primary_key :id
|
14
|
+
String :fully_qualified_name, null: false, unique: true
|
15
|
+
index :fully_qualified_name
|
16
|
+
end
|
17
|
+
|
18
|
+
run <<-"EOSQL"
|
19
|
+
INSERT INTO #{lookup_table_name} (fully_qualified_name)
|
20
|
+
SELECT DISTINCT fully_qualified_name FROM #{event_store_table_name}
|
21
|
+
EOSQL
|
22
|
+
|
23
|
+
alter_table(event_store_table) do
|
24
|
+
idx_name = "aggregate_id_occurred_at_fqn_id_idx"
|
25
|
+
add_foreign_key :fully_qualified_name_id, lookup_table, key: :id, null: false
|
26
|
+
add_index([:aggregate_id, :occurred_at, :fully_qualified_name_id], name: idx_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
run <<-"EOSQL"
|
30
|
+
UPDATE #{event_store_table_name} AS event_store
|
31
|
+
SET fully_qualified_name_id = lookup.id
|
32
|
+
FROM #{lookup_table_name} AS lookup
|
33
|
+
WHERE lookup.fully_qualified_name = event_store.fully_qualified_name
|
34
|
+
EOSQL
|
35
|
+
|
36
|
+
alter_table(event_store_table) do
|
37
|
+
old_idx_name = "#{EventStore.schema}_#{EventStore.table_name}_aggregate_id_occurred_at_name_idx"
|
38
|
+
drop_index [:aggregate_id, :occurred_at, :fully_qualified_name], name: old_idx_name
|
39
|
+
drop_index :fully_qualified_name
|
40
|
+
drop_column :fully_qualified_name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
down do
|
45
|
+
alter_table(event_store_table) do
|
46
|
+
idx_name = "#{EventStore.schema}_#{EventStore.table_name}_aggregate_id_occurred_at_name_idx"
|
47
|
+
old_idx_name = "aggregate_id_occurred_at_fqn_id_idx"
|
48
|
+
|
49
|
+
add_column :fully_qualified_name, String
|
50
|
+
add_index :fully_qualified_name
|
51
|
+
add_index([:aggregate_id, :occurred_at, :fully_qualified_name], name: idx_name)
|
52
|
+
drop_index old_idx_name
|
53
|
+
end
|
54
|
+
|
55
|
+
run <<-"EOSQL"
|
56
|
+
UPDATE #{event_store_table_name} AS event_store
|
57
|
+
SET fully_qualified_name = lookup.fully_qualified_name
|
58
|
+
FROM #{lookup_table_name} AS lookup
|
59
|
+
WHERE lookup.id = event_store.fully_qualified_name_id
|
60
|
+
EOSQL
|
61
|
+
|
62
|
+
alter_table(event_store_table) do
|
63
|
+
drop_foreign_key :fully_qualified_name_id
|
64
|
+
end
|
65
|
+
|
66
|
+
drop_table(lookup_table)
|
67
|
+
end
|
68
|
+
end
|
@@ -7,7 +7,10 @@ module EventStore
|
|
7
7
|
def initialize aggregate
|
8
8
|
@aggregate = aggregate
|
9
9
|
@id = @aggregate.id
|
10
|
-
@
|
10
|
+
@event_table_alias = "events"
|
11
|
+
@event_table = "#{EventStore.schema}__#{EventStore.table_name}".to_sym
|
12
|
+
@aliased_event_table = "#{event_table}___#{@event_table_alias}".to_sym
|
13
|
+
@names_table = EventStore.fully_qualified_names_table
|
11
14
|
end
|
12
15
|
|
13
16
|
def append(raw_events)
|
@@ -17,20 +20,38 @@ module EventStore
|
|
17
20
|
event
|
18
21
|
end
|
19
22
|
|
20
|
-
|
21
|
-
prepared_events.
|
22
|
-
event
|
23
|
+
event_table = EventStore.db.from(@event_table)
|
24
|
+
prepared_events.each do |event|
|
25
|
+
event_hash = event.dup.reject! { |k,v| k == :fully_qualified_name }
|
26
|
+
|
27
|
+
begin
|
28
|
+
id = event_table.insert(event_hash)
|
29
|
+
rescue Sequel::NotNullConstraintViolation
|
30
|
+
fully_qualified_names.insert(fully_qualified_name: event[:fully_qualified_name])
|
31
|
+
id = event_table.insert(event_hash)
|
32
|
+
end
|
33
|
+
|
34
|
+
event[:id] = id
|
23
35
|
end
|
24
36
|
|
25
37
|
yield(prepared_events) if block_given?
|
26
38
|
end
|
27
39
|
|
40
|
+
def fully_qualified_names
|
41
|
+
@fully_qualified_name_query ||= EventStore.db.from(@names_table)
|
42
|
+
end
|
43
|
+
|
28
44
|
def events
|
29
|
-
@events_query ||= EventStore.db.from(@
|
45
|
+
@events_query ||= EventStore.db.from(@aliased_event_table) \
|
46
|
+
.where(:aggregate_id => @id.to_s) \
|
47
|
+
.join(@names_table, id: :fully_qualified_name_id) \
|
48
|
+
.order("#{@event_table_alias}__id".to_sym) \
|
49
|
+
.select_all(:events).select_append(:fully_qualified_name)
|
30
50
|
end
|
31
51
|
|
32
52
|
def events_from(event_id, max = nil)
|
33
|
-
events
|
53
|
+
# note: this depends on the events table being aliased to "events" above.
|
54
|
+
events.limit(max).where{events__id >= event_id.to_i }.all.map do |event|
|
34
55
|
event[:serialized_event] = EventStore.unescape_bytea(event[:serialized_event])
|
35
56
|
event
|
36
57
|
end
|
@@ -69,18 +90,19 @@ module EventStore
|
|
69
90
|
end
|
70
91
|
|
71
92
|
def delete_events!
|
72
|
-
|
93
|
+
EventStore.db.from(@event_table).where(:aggregate_id => @id.to_s).delete
|
73
94
|
end
|
74
95
|
|
75
96
|
private
|
76
97
|
|
77
98
|
def prepare_event(raw_event)
|
78
99
|
raise ArgumentError.new("Cannot Append a Nil Event") unless raw_event
|
79
|
-
{ :aggregate_id
|
80
|
-
:occurred_at
|
81
|
-
:serialized_event
|
82
|
-
:
|
83
|
-
:
|
100
|
+
{ :aggregate_id => raw_event.aggregate_id,
|
101
|
+
:occurred_at => Time.parse(raw_event.occurred_at.to_s).utc, #to_s truncates microseconds, which brake Time equality
|
102
|
+
:serialized_event => EventStore.escape_bytea(raw_event.serialized_event),
|
103
|
+
:fully_qualified_name_id => EventStore.db.from(@names_table).where(fully_qualified_name: raw_event.fully_qualified_name).select(:id),
|
104
|
+
:fully_qualified_name => raw_event.fully_qualified_name,
|
105
|
+
:sub_key => raw_event.sub_key
|
84
106
|
}
|
85
107
|
end
|
86
108
|
|
data/lib/event_store/version.rb
CHANGED
data/lib/event_store.rb
CHANGED
@@ -64,10 +64,18 @@ module EventStore
|
|
64
64
|
@table_name ||= raw_db_config['table_name']
|
65
65
|
end
|
66
66
|
|
67
|
+
def self.lookup_table_name
|
68
|
+
@lookup_table_name ||= raw_db_config['lookup_table_name'] || "fully_qualified_names"
|
69
|
+
end
|
70
|
+
|
67
71
|
def self.fully_qualified_table
|
68
72
|
@fully_qualified_table ||= Sequel.lit "#{schema}.#{table_name}"
|
69
73
|
end
|
70
74
|
|
75
|
+
def self.fully_qualified_names_table
|
76
|
+
@fully_qualified_names_table ||= Sequel.lit "#{schema}.#{lookup_table_name}"
|
77
|
+
end
|
78
|
+
|
71
79
|
def self.connected?
|
72
80
|
!!EventStore.db
|
73
81
|
end
|
@@ -52,7 +52,7 @@ describe EventStore::Client do
|
|
52
52
|
raw_stream = es_client.new(AGGREGATE_ID_ONE, :device).raw_event_stream
|
53
53
|
raw_event = raw_stream.first
|
54
54
|
expect(raw_event.class).to eq(Hash)
|
55
|
-
expect(raw_event.keys).to eq([:id, :version, :aggregate_id, :fully_qualified_name, :occurred_at, :serialized_event, :sub_key])
|
55
|
+
expect(raw_event.keys.to_set).to eq(Set.new([:id, :version, :aggregate_id, :fully_qualified_name, :fully_qualified_name_id, :occurred_at, :serialized_event, :sub_key]))
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'should be empty for aggregates without events' do
|
@@ -108,14 +108,14 @@ describe EventStore::Client do
|
|
108
108
|
client = es_client.new("any_device", :device)
|
109
109
|
serialized_event = serialized_event_data_terminated_by_null
|
110
110
|
event = EventStore::Event.new("any_device", @event_time, 'terminated_by_null_event', "zone_number", serialized_event)
|
111
|
-
client.append([event])
|
112
|
-
hex_from_db = EventStore.db.from(EventStore.fully_qualified_table).
|
111
|
+
retval = client.append([event])
|
112
|
+
hex_from_db = EventStore.db.from(EventStore.fully_qualified_table).order(:id).last[:serialized_event]
|
113
|
+
|
113
114
|
expect(hex_from_db).to eql(EventStore.escape_bytea(serialized_event))
|
114
115
|
end
|
115
116
|
end
|
116
117
|
end
|
117
118
|
|
118
|
-
|
119
119
|
describe '#raw_event_streams_from_event_id' do
|
120
120
|
subject { es_client.new(AGGREGATE_ID_ONE, :device) }
|
121
121
|
let(:raw_stream) { subject.raw_event_stream }
|
@@ -243,7 +243,7 @@ describe EventStore::Client do
|
|
243
243
|
let(:client) { es_client.new(AGGREGATE_ID_ONE, :device) }
|
244
244
|
|
245
245
|
it 'should return the last event in the event stream' do
|
246
|
-
last_event =
|
246
|
+
last_event = client.raw_event_stream.last
|
247
247
|
peek = client.peek
|
248
248
|
expect(peek.fully_qualified_name).to eq(last_event[:fully_qualified_name])
|
249
249
|
expect(peek.event_id).to eq(last_event[:id])
|
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.7.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: 2015-
|
12
|
+
date: 2015-05-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -231,6 +231,8 @@ files:
|
|
231
231
|
- db/migrations/001_create_event_store_events.rb
|
232
232
|
- db/pg_migrations/001_create_event_store_events.rb
|
233
233
|
- db/pg_migrations/002_create_event_store_events.rb
|
234
|
+
- db/pg_migrations/003_add_agg_id_occurred_fqn_idx_to_event_store.rb
|
235
|
+
- db/pg_migrations/004_add_fqn_lookup_table_to_event_store.rb
|
234
236
|
- db/setup_db_user.sql
|
235
237
|
- event_store.gemspec
|
236
238
|
- lib/event_store.rb
|