event_store 0.1.5 → 0.1.6

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.
data/.simplecov ADDED
@@ -0,0 +1,16 @@
1
+ require 'simplecov'
2
+ require 'simplecov-rcov'
3
+
4
+ class SimpleCov::Formatter::MergedFormatter
5
+ def format(result)
6
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
7
+ SimpleCov::Formatter::RcovFormatter.new.format(result)
8
+ end
9
+ end
10
+ SimpleCov.formatter = SimpleCov::Formatter::MergedFormatter
11
+
12
+ SimpleCov.start do
13
+ add_filter "_spec.rb"
14
+
15
+ SimpleCov.minimum_coverage 96
16
+ end
data/Rakefile CHANGED
@@ -4,6 +4,11 @@ RSpec::Core::RakeTask.new(:'spec:ci')
4
4
 
5
5
  task :default => :'spec:ci'
6
6
 
7
+ def rspec_out_file
8
+ require 'rspec_junit_formatter'
9
+ "-f RspecJunitFormatter -o results.xml"
10
+ end
11
+
7
12
  desc "Seed the performance db with millions of events"
8
13
  task :'db:seed:perf' do
9
14
  sh 'time bundle exec ruby spec/benchmark/seed_db.rb'
@@ -12,4 +17,9 @@ end
12
17
  desc "Run the performance benchmarks on the performance db"
13
18
  task :benchmark do
14
19
  sh 'bundle exec ruby spec/benchmark/bench.rb'
15
- end
20
+ end
21
+
22
+ desc "Run all tests and generate coverage xml"
23
+ task :'spec:cov' do
24
+ sh "bundle exec rspec #{rspec_out_file} spec"
25
+ end
@@ -1,6 +1,6 @@
1
1
  # require_relative '../../protocol_buffers/lib/protocol_buffers'
2
2
  require 'faceplate_api'
3
- require "faceplate_api/thermostats/test_support/event_mother"
3
+ require "faceplate_api/thermostats/test_support"
4
4
  require 'securerandom'
5
5
  require 'time'
6
6
  include FaceplateApi
@@ -15,7 +15,7 @@ versions_per_device = (0..(event_names.length * ITERATIONS)).to_a
15
15
 
16
16
  mothers = {}
17
17
  aggregate_ids.each do |aggregate_id|
18
- mother = Thermostats::EventMother.new(device_id: aggregate_id)
18
+ mother = FaceplateApi::EventFixture.new(header: {device_id: aggregate_id}).event_mother
19
19
  mothers[mother] = versions_per_device.dup
20
20
  end
21
21
 
data/event_store.gemspec CHANGED
@@ -32,4 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.add_dependency 'pg', '~> 0.17.1'
33
33
  spec.add_dependency 'redis', "~> 3.0.7"
34
34
  spec.add_dependency 'hiredis'
35
+ spec.add_development_dependency 'rspec_junit_formatter'
35
36
  end
@@ -23,7 +23,7 @@ module EventStore
23
23
  raw_event = value.split(EventStore::SNAPSHOT_DELIMITER)
24
24
  fully_qualified_name = key
25
25
  version = raw_event.first.to_i
26
- serialized_event = raw_event[1]
26
+ serialized_event = EventStore.unescape_bytea(raw_event[1])
27
27
  occurred_at = Time.parse(raw_event.last)
28
28
  snap << SerializedEvent.new(fully_qualified_name, serialized_event, version, occurred_at)
29
29
  end
@@ -81,7 +81,7 @@ module EventStore
81
81
 
82
82
  def translate_event(event_hash)
83
83
  occurred_at = TimeHacker.translate_occurred_at_from_local_to_gmt(event_hash[:occurred_at])
84
- SerializedEvent.new event_hash[:fully_qualified_name], event_hash[:serialized_event], event_hash[:version], occurred_at
84
+ SerializedEvent.new event_hash[:fully_qualified_name], EventStore.unescape_bytea(event_hash[:serialized_event]), event_hash[:version], occurred_at
85
85
  end
86
86
  end
87
87
  end
@@ -57,7 +57,7 @@ module EventStore
57
57
  { :version => raw_event.version.to_i,
58
58
  :aggregate_id => raw_event.aggregate_id,
59
59
  :occurred_at => Time.parse(raw_event.occurred_at.to_s).utc, #to_s truncates microseconds, which brake Time equality
60
- :serialized_event => raw_event.serialized_event,
60
+ :serialized_event => EventStore.escape_bytea(raw_event.serialized_event),
61
61
  :fully_qualified_name => raw_event.fully_qualified_name }
62
62
  end
63
63
 
@@ -1,3 +1,3 @@
1
1
  module EventStore
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.6"
3
3
  end
data/lib/event_store.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'sequel'
2
+ require 'sequel_core'
2
3
  require 'vertica'
3
4
  require 'sequel-vertica'
4
5
  require 'redis'
@@ -90,6 +91,19 @@ module EventStore
90
91
  create_db
91
92
  end
92
93
 
94
+ def self.escape_bytea(binary_string)
95
+ @adapter == 'vertica' ? binary_string : EventStore.db.literal(binary_string.to_sequel_blob)
96
+ end
97
+
98
+ def self.unescape_bytea(binary_string)
99
+ if @adapter == 'vertica'
100
+ binary_string
101
+ else
102
+ unescaped = Sequel::Postgres::Adapter.unescape_bytea(binary_string)
103
+ unescaped[0] == "'" && unescaped[-1] == "'" ? unescaped[1...-1] : unescaped #postgres adds an extra set of quotes when you insert it, Redis does not. Therefore we need to pull off the extra quotes if they are there
104
+ end
105
+ end
106
+
93
107
  def self.custom_config(database_config, redis_config, envrionment = 'production')
94
108
  self.redis_connect(redis_config)
95
109
  @adapter = database_config['adapter'].to_s
@@ -1,24 +1,28 @@
1
1
  require 'spec_helper'
2
+ require 'securerandom'
3
+ AGGREGATE_ID_ONE = SecureRandom.uuid
4
+ AGGREGATE_ID_TWO = SecureRandom.uuid
5
+ AGGREGATE_ID_THREE = SecureRandom.uuid
2
6
 
3
7
  describe EventStore::Client do
4
8
  let(:es_client) { EventStore::Client }
5
9
 
6
10
  before do
7
- client_1 = es_client.new('1', :device)
8
- client_2 = es_client.new('2', :device)
11
+ client_1 = es_client.new(AGGREGATE_ID_ONE, :device)
12
+ client_2 = es_client.new(AGGREGATE_ID_TWO, :device)
9
13
 
10
- events_by_aggregate_id = {'1' => [], '2' => []}
14
+ events_by_aggregate_id = {AGGREGATE_ID_ONE => [], AGGREGATE_ID_TWO => []}
11
15
  @event_time = Time.parse("2001-01-01 00:00:00 UTC")
12
- ([1]*10 + [2]*10).shuffle.each_with_index do |aggregate_id, version|
13
- events_by_aggregate_id[aggregate_id.to_s] << EventStore::Event.new(aggregate_id.to_s, @event_time, 'event_name', "#{234532.to_s(2)}_foo}", version)
16
+ ([AGGREGATE_ID_ONE]*10 + [AGGREGATE_ID_TWO]*10).shuffle.each_with_index do |aggregate_id, version|
17
+ events_by_aggregate_id[aggregate_id.to_s] << EventStore::Event.new(aggregate_id.to_s, @event_time, 'event_name', serialized_binary_event_data, version)
14
18
  end
15
- client_1.append events_by_aggregate_id['1']
16
- client_2.append events_by_aggregate_id['2']
19
+ client_1.append events_by_aggregate_id[AGGREGATE_ID_ONE]
20
+ client_2.append events_by_aggregate_id[AGGREGATE_ID_TWO]
17
21
  end
18
22
 
19
23
  describe '#raw_event_stream' do
20
24
  it "should be an array of hashes that represent database records, not EventStore::SerializedEvent objects" do
21
- raw_stream = es_client.new(1, :device).raw_event_stream
25
+ raw_stream = es_client.new(AGGREGATE_ID_ONE, :device).raw_event_stream
22
26
  raw_stream.class.should == Array
23
27
  raw_event = raw_stream.first
24
28
  raw_event.class.should == Hash
@@ -31,19 +35,19 @@ describe EventStore::Client do
31
35
  end
32
36
 
33
37
  it 'should only have events for a single aggregate' do
34
- stream = es_client.new(1, :device).raw_event_stream
35
- stream.each { |event| event[:aggregate_id].should == '1' }
38
+ stream = es_client.new(AGGREGATE_ID_ONE, :device).raw_event_stream
39
+ stream.each { |event| event[:aggregate_id].should == AGGREGATE_ID_ONE }
36
40
  end
37
41
 
38
42
  it 'should have all events for that aggregate' do
39
- stream = es_client.new(1, :device).raw_event_stream
43
+ stream = es_client.new(AGGREGATE_ID_ONE, :device).raw_event_stream
40
44
  expect(stream.count).to eq(10)
41
45
  end
42
46
  end
43
47
 
44
48
  describe '#event_stream' do
45
49
  it "should be an array of EventStore::SerializedEvent objects" do
46
- stream = es_client.new(1, :device).event_stream
50
+ stream = es_client.new(AGGREGATE_ID_ONE, :device).event_stream
47
51
  stream.class.should == Array
48
52
  event = stream.first
49
53
  event.class.should == EventStore::SerializedEvent
@@ -55,20 +59,20 @@ describe EventStore::Client do
55
59
  end
56
60
 
57
61
  it 'should only have events for a single aggregate' do
58
- raw_stream = es_client.new(1, :device).raw_event_stream
59
- stream = es_client.new(1, :device).event_stream
62
+ raw_stream = es_client.new(AGGREGATE_ID_ONE, :device).raw_event_stream
63
+ stream = es_client.new(AGGREGATE_ID_ONE, :device).event_stream
60
64
  stream.map(&:fully_qualified_name).should == raw_stream.inject([]){|m, event| m << event[:fully_qualified_name]; m}
61
65
  end
62
66
 
63
67
  it 'should have all events for that aggregate' do
64
- stream = es_client.new(1, :device).event_stream
68
+ stream = es_client.new(AGGREGATE_ID_ONE, :device).event_stream
65
69
  expect(stream.count).to eq(10)
66
70
  end
67
71
  end
68
72
 
69
73
 
70
74
  describe '#raw_event_streams_from_version' do
71
- subject { es_client.new(1, :device) }
75
+ subject { es_client.new(AGGREGATE_ID_ONE, :device) }
72
76
 
73
77
  it 'should return all the raw events in the stream starting from a certain version' do
74
78
  minimum_event_version = 2
@@ -91,7 +95,7 @@ describe EventStore::Client do
91
95
  end
92
96
 
93
97
  describe 'event_stream_from_version' do
94
- subject { es_client.new(1, :device) }
98
+ subject { es_client.new(AGGREGATE_ID_ONE, :device) }
95
99
 
96
100
  it 'should return all the raw events in the stream starting from a certain version' do
97
101
  minimum_event_version = 2
@@ -114,24 +118,24 @@ describe EventStore::Client do
114
118
  end
115
119
 
116
120
  describe '#peek' do
117
- let(:client) {es_client.new(1, :device)}
121
+ let(:client) {es_client.new(AGGREGATE_ID_ONE, :device)}
118
122
  subject { client.peek }
119
123
 
120
124
  it 'should return the last event in the event stream' do
121
- last_event = EventStore.db.from(client.event_table).where(aggregate_id: '1').order(:version).last
122
- subject.should == EventStore::SerializedEvent.new(last_event[:fully_qualified_name], last_event[:serialized_event].to_s, last_event[:version], @event_time)
125
+ last_event = EventStore.db.from(client.event_table).where(aggregate_id: AGGREGATE_ID_ONE).order(:version).last
126
+ subject.should == EventStore::SerializedEvent.new(last_event[:fully_qualified_name], EventStore.unescape_bytea(last_event[:serialized_event]), last_event[:version], @event_time)
123
127
  end
124
128
  end
125
129
 
126
130
  describe '#append' do
127
131
  before do
128
- @client = EventStore::Client.new('1', :device)
132
+ @client = EventStore::Client.new(AGGREGATE_ID_ONE, :device)
129
133
  @event = @client.peek
130
134
  version = @client.version
131
- @old_event = EventStore::Event.new('1', (@event_time - 2000).utc, "old", "#{1000.to_s(2)}_foo", version += 1)
132
- @new_event = EventStore::Event.new('1', (@event_time - 1000).utc, "new", "#{1001.to_s(2)}_foo", version += 1)
133
- @really_new_event = EventStore::Event.new('1', (@event_time + 100).utc, "really_new", "#{1002.to_s(2)}_foo", version += 1)
134
- @duplicate_event = EventStore::Event.new('1', (@event_time).utc, 'duplicate', "#{12.to_s(2)}_foo", version += 1)
135
+ @old_event = EventStore::Event.new(AGGREGATE_ID_ONE, (@event_time - 2000).utc, "old", "#{1000.to_s(2)}_foo", version += 1)
136
+ @new_event = EventStore::Event.new(AGGREGATE_ID_ONE, (@event_time - 1000).utc, "new", "#{1001.to_s(2)}_foo", version += 1)
137
+ @really_new_event = EventStore::Event.new(AGGREGATE_ID_ONE, (@event_time + 100).utc, "really_new", "#{1002.to_s(2)}_foo", version += 1)
138
+ @duplicate_event = EventStore::Event.new(AGGREGATE_ID_ONE, (@event_time).utc, 'duplicate', "#{12.to_s(2)}_foo", version += 1)
135
139
  end
136
140
 
137
141
  describe "when expected version number is greater than the last version" do
@@ -250,17 +254,17 @@ describe EventStore::Client do
250
254
 
251
255
  describe 'snapshot' do
252
256
  before do
253
- @client = es_client.new('10', :device)
257
+ @client = es_client.new(AGGREGATE_ID_THREE, :device)
254
258
  @client.snapshot.length.should == 0
255
259
  version = @client.version
256
- @client.append %w{ e1 e2 e3 e1 e2 e4 e5 e2 e5 e4}.map {|fqn|EventStore::Event.new('10', Time.now.utc, fqn, 234532.to_s(2), version += 1)}
260
+ @client.append %w{ e1 e2 e3 e1 e2 e4 e5 e2 e5 e4}.map {|fqn|EventStore::Event.new(AGGREGATE_ID_THREE, Time.now.utc, fqn, serialized_binary_event_data, version += 1)}
257
261
  end
258
262
 
259
263
  it "finds the most recent records for each type" do
260
264
  version = @client.version
261
- expected_snapshot = %w{ e1 e2 e3 e4 e5 }.map {|fqn| EventStore::SerializedEvent.new(fqn, 234532.to_s(2), version +=1 ) }
262
- @client.event_stream.length.should == 10
265
+ expected_snapshot = %w{ e1 e2 e3 e4 e5 }.map {|fqn| EventStore::SerializedEvent.new(fqn, serialized_binary_event_data, version +=1 ) }
263
266
  actual_snapshot = @client.snapshot
267
+ @client.event_stream.length.should == 10
264
268
  actual_snapshot.length.should == 5
265
269
  actual_snapshot.map(&:fully_qualified_name).should == ["e3", "e1", "e2", "e5", "e4"] #sorted by version no
266
270
  actual_snapshot.map(&:serialized_event).should == expected_snapshot.map(&:serialized_event)
@@ -283,5 +287,10 @@ describe EventStore::Client do
283
287
  aggregate = client.instance_variable_get("@aggregate")
284
288
  EventStore.redis.hset(aggregate.snapshot_version_table, :current_version, 1000)
285
289
  end
290
+
291
+ end
292
+ def serialized_binary_event_data
293
+ @event_data ||= File.open(File.expand_path("../serialized_binary_event_data.txt", __FILE__), 'rb') {|f| f.read}
294
+ @event_data
286
295
  end
287
296
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-02-15 00:00:00.000000000 Z
13
+ date: 2014-03-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -220,6 +220,22 @@ dependencies:
220
220
  - - ! '>='
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: rspec_junit_formatter
225
+ requirement: !ruby/object:Gem::Requirement
226
+ none: false
227
+ requirements:
228
+ - - ! '>='
229
+ - !ruby/object:Gem::Version
230
+ version: '0'
231
+ type: :development
232
+ prerelease: false
233
+ version_requirements: !ruby/object:Gem::Requirement
234
+ none: false
235
+ requirements:
236
+ - - ! '>='
237
+ - !ruby/object:Gem::Version
238
+ version: '0'
223
239
  description: ! '["A Ruby implementation of an EventSource (A+ES) tuned for Vertica
224
240
  or Postgres"]'
225
241
  email:
@@ -230,6 +246,7 @@ extra_rdoc_files: []
230
246
  files:
231
247
  - .gitignore
232
248
  - .rspec
249
+ - .simplecov
233
250
  - Gemfile
234
251
  - Guardfile
235
252
  - LICENSE.txt
@@ -269,12 +286,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
269
286
  - - ! '>='
270
287
  - !ruby/object:Gem::Version
271
288
  version: '0'
289
+ segments:
290
+ - 0
291
+ hash: -3767686812779732667
272
292
  required_rubygems_version: !ruby/object:Gem::Requirement
273
293
  none: false
274
294
  requirements:
275
295
  - - ! '>='
276
296
  - !ruby/object:Gem::Version
277
297
  version: '0'
298
+ segments:
299
+ - 0
300
+ hash: -3767686812779732667
278
301
  requirements: []
279
302
  rubyforge_project:
280
303
  rubygems_version: 1.8.25
@@ -289,4 +312,3 @@ test_files:
289
312
  - spec/event_store/snapshot_spec.rb
290
313
  - spec/event_store/vertica guy notes.txt
291
314
  - spec/spec_helper.rb
292
- has_rdoc: