event_store 0.1.5 → 0.1.6

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