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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 115b1bb8a9f14f799f97b9038cf9ae1ed8a9aacd
4
- data.tar.gz: b1e31142a7fda060e2f4b2cd1a81a3c0cc8dc652
3
+ metadata.gz: 810f954e899ec5777b6f4b57431d9739734f8519
4
+ data.tar.gz: b0fc4fae467b95e007d317894206618d9ada5899
5
5
  SHA512:
6
- metadata.gz: 46eac58f16227a98364a52a33c0c9d8f91c1dcbfd8047c52373e4a0d0ea131a6f16324a5ccd54b7c21d2781f6903b2c312dbba32ad951b55bdb1fe4cf2d72671
7
- data.tar.gz: 1f6c50f1f137024ac13b1a683b68815ea34e7f833555a66624b9bb885f2917b96708d8f06749af111164756bd0822da0c16de56269703e914f7ea937a92f3385
6
+ metadata.gz: 74d45ebf5fe97fdb52e067b17885be10159e2a94200671b1fa106a75e90e6428e33a362ded5a481c92d762981c5e9cba56f60126960bc34216845ccea3306045
7
+ data.tar.gz: 58ed1ef36e12724c2ee1ea689af1eeb3d85164677c800aadac21a2ac11b20d92b09e590a05162595b1f44cc35afb2c2d95b71dacd2689e5dd3ed1c7587e60170
data/db/database.yml CHANGED
@@ -35,8 +35,8 @@ test:
35
35
  postgres:
36
36
  <<: *postgres
37
37
  database: history_store
38
- schema: event_store_gem_test
38
+ schema: es_test
39
39
  vertica:
40
40
  <<: *vertica
41
41
  database: history_store
42
- schema: event_store_gem_test
42
+ schema: es_test
@@ -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
- @event_table = EventStore.fully_qualified_table
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
- inserted_ids = events.multi_insert(prepared_events, return: :primary_key)
21
- prepared_events.each_with_index do |event, idx|
22
- event[:id] = inserted_ids[idx]
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(@event_table).where(:aggregate_id => @id.to_s).order(:id)
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.limit(max).where{ id >= event_id.to_i }.all.map do |event|
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
- events.delete
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 => raw_event.aggregate_id,
80
- :occurred_at => Time.parse(raw_event.occurred_at.to_s).utc, #to_s truncates microseconds, which brake Time equality
81
- :serialized_event => EventStore.escape_bytea(raw_event.serialized_event),
82
- :fully_qualified_name => raw_event.fully_qualified_name,
83
- :sub_key => raw_event.sub_key
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
 
@@ -1,3 +1,3 @@
1
1
  module EventStore
2
- VERSION = '0.6.1'
2
+ VERSION = '0.7.0'
3
3
  end
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).where(fully_qualified_name: 'terminated_by_null_event').first[:serialized_event]
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 = EventStore.db.from(client.event_table).where(aggregate_id: AGGREGATE_ID_ONE).order(:id).last
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.6.1
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-04-29 00:00:00.000000000 Z
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