eventus 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8f07f4c662a87341402536914257548434f11118
4
- data.tar.gz: f3e4d1fbc6080b8eae3943b40c599fb9080673be
3
+ metadata.gz: bd0b08439ed10730278782f0c345e05ce2dfe151
4
+ data.tar.gz: ae83a990fd2d9d8bf2acaf17264517310a36a998
5
5
  SHA512:
6
- metadata.gz: d348c4ef193bb481caa262b28725be1081bb140d23870dc08ee73167a730627cf94e1d53cffdc9a28339f8fe7e2773e984d69fa12e69bef9ec81ca701167316a
7
- data.tar.gz: 0c5ed83d2c4c963c9b636ca431c29d03e86e1f9f7586b22f08a8e9cca3c87a740d969fc1b758738f05ef7ea29e08ab422ceefb52db18406ae0a5267cce6bfad2
6
+ metadata.gz: 040f8cb4ba662af9899402fa9e865d03054a88ca4062a41c15e4a59e9be1964c309294cb00fdb6eee9cc54ba7b9064ede144fc13531aacac558c390cd88830f1
7
+ data.tar.gz: 1cb838126015dc629732c390f33646443580c718052257a7ab374784a4ee27be5e2c01b22e8e35854630674f4fbf8a31696465f23936cc01b313fcac04e97c54
data/Gemfile CHANGED
@@ -1,14 +1,3 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
-
5
- group :development do
6
- gem 'rake'
7
- gem 'rspec'
8
- gem 'uuid'
9
- gem 'mongo'
10
- gem 'bson_ext', :platforms => [:mri, :rbx]
11
- gem 'redis'
12
-
13
- gem 'kyotocabinet-ruby', :platforms => [:mri, :rbx] unless ENV['TRAVIS']
14
- end
data/eventus.gemspec CHANGED
@@ -17,4 +17,15 @@ Gem::Specification.new do |s|
17
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency 'rake'
22
+ s.add_development_dependency 'rspec', '~>2.0'
23
+ s.add_development_dependency 'uuid'
24
+ s.add_development_dependency 'mongo'
25
+ s.add_development_dependency 'bson_ext'
26
+ s.add_development_dependency 'redis'
27
+ s.add_development_dependency 'kyotocabinet-ruby'
28
+ s.add_development_dependency 'sequel'
29
+ s.add_development_dependency 'sqlite3'
30
+ s.add_development_dependency 'sequel-enhancements'
20
31
  end
@@ -0,0 +1,22 @@
1
+ Sequel.migration do
2
+ up do
3
+ create_table :eventus_events do
4
+ primary_key :id
5
+ column :name, String, null: false
6
+ column :time, DateTime, null: false
7
+ column :sid, String, null: false
8
+ column :sequence, Integer, null: false
9
+ column :dispatched, TrueClass, null: false, default: false
10
+ column :body, :json, null: false
11
+
12
+ unique [:sid, :sequence]
13
+ index :sid
14
+ index :time
15
+ end
16
+ end
17
+
18
+ down do
19
+ drop_table :eventus_events
20
+ end
21
+ end
22
+
@@ -0,0 +1,54 @@
1
+ module Eventus
2
+ module Persistence
3
+ class Sequel
4
+ MIGRATIONS_PATH = File.expand_path('../sequel/migrations', __FILE__).freeze
5
+ TABLE_NAME = :eventus_events
6
+
7
+ attr_reader :dataset, :db
8
+
9
+ def initialize(db)
10
+ @db = db
11
+ @dataset = db[TABLE_NAME]
12
+ @dataset.row_proc = method :convert_row
13
+ end
14
+
15
+ def commit(events)
16
+ @db.transaction(:savepoint => true) do
17
+ events.each do |event|
18
+ event['body'] = db.typecast_value(:json, event['body'])
19
+ end
20
+ @dataset.multi_insert(events)
21
+ end
22
+ rescue ::Sequel::UniqueConstraintViolation
23
+ raise Eventus::ConcurrencyError
24
+ end
25
+
26
+ def load(sid, min=nil)
27
+ events = @dataset.where(:sid => sid)
28
+ events = events.where{ sequence >= min } if min
29
+ events.all
30
+ end
31
+
32
+ def load_undispatched
33
+ @dataset.where(:dispatched => false).all
34
+ end
35
+
36
+ def mark_dispatched(sid, sequence)
37
+ @dataset
38
+ .where(:sid => sid, :sequence => sequence)
39
+ .update(:dispatched => true)
40
+ end
41
+
42
+ def convert_row(row)
43
+ row.each_with_object({}) do |(k,v), memo|
44
+ memo[k.to_s] = v
45
+ end
46
+ end
47
+
48
+ def self.migrate!(db)
49
+ ::Sequel.extension :migration
50
+ ::Sequel::Migrator.run(db, MIGRATIONS_PATH, :table => :eventus_schema)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -4,5 +4,6 @@ module Eventus
4
4
  autoload :Mongo, 'eventus/persistence/mongo'
5
5
  autoload :Redis, 'eventus/persistence/redis'
6
6
  autoload :InMemory, 'eventus/persistence/in_memory'
7
+ autoload :Sequel, 'eventus/persistence/sequel'
7
8
  end
8
9
  end
@@ -1,3 +1,3 @@
1
1
  module Eventus
2
- VERSION = "0.5.1"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe Eventus::Persistence::Sequel do
4
+ let(:persistence) { Eventus::Persistence::Sequel.new(@db) }
5
+ let(:uuid) { UUID.new }
6
+
7
+ before(:all) { @db = Sequel::DATABASES.first }
8
+
9
+ it "should store complex objects" do
10
+ id = uuid.generate :compact
11
+ o = {'a' => 'super', 'complex' => ['object', 'with', {'nested' => ['members', 'galore', 1]}]}
12
+ commit = create_commit(id, 1, o)
13
+ persistence.commit(commit)
14
+ event = commit[0]
15
+
16
+ result = persistence.load(id)[0]
17
+ result['name'].should == event['name']
18
+ result['sid'].should == event['sid']
19
+ result['time'].should == Time.parse(event['time'])
20
+ result['sequence'].should == event['sequence']
21
+ result['dispatched'].should be_false
22
+ result['body'].should == event['body']
23
+ end
24
+
25
+ it "should return no events when key not found" do
26
+ result = persistence.load "my_id"
27
+ result.should be_empty
28
+ end
29
+
30
+ it "should return events ordered" do
31
+ id = uuid.generate :compact
32
+ persistence.commit create_commit(id, 1, {"foo" => "one"}, {"foo" => "two"})
33
+ persistence.commit create_commit(id, 3, {"foo" => "three"}, {"foo" => "four"})
34
+ persistence.commit create_commit(id, 5, {"foo" => "five"}, {"foo" => "six"})
35
+ persistence.commit create_commit("other", 1, {"foo" => "cake"}, {"foo" => "batter"})
36
+
37
+ result = persistence.load id
38
+ result.map{|r| r['body']['foo']}.should == ["one", "two", "three", "four", "five", "six"]
39
+ end
40
+
41
+ describe "when events exist" do
42
+ let(:id) { uuid.generate :compact }
43
+ let(:events) { create_commit(id, 1, *(1..20).map{|i| {'foo' => i}}).each_with_index{ |e,i| e['dispatched'] = i.even? } }
44
+ before do
45
+ other_id = uuid.generate :compact
46
+ persistence.commit events
47
+ other_events = create_commit(other_id, 1, *(1..60).map{|i| {'foo' => i}}).each_with_index {|e,i| e['dispatched'] = i.even? }
48
+ persistence.commit other_events
49
+ end
50
+
51
+ it "should load events" do
52
+ result = persistence.load id
53
+ result.length.should == 20
54
+ end
55
+
56
+ it "should load undispatched events" do
57
+ result = persistence.load_undispatched
58
+ result.select{|r| r['sid'] == id}.length.should == 10
59
+ end
60
+
61
+ it "should mark an event as dispatched" do
62
+ result = persistence.load_undispatched[0]
63
+ persistence.mark_dispatched(result['sid'], result['sequence'])
64
+ persistence.load_undispatched.include?(result).should be_false
65
+ end
66
+
67
+ it "should throw concurrency exception if the same event number is added" do
68
+ expect {persistence.commit create_commit(id, 3, {"foo" => "This is taken"})}.to raise_error(Eventus::ConcurrencyError)
69
+ end
70
+
71
+ it "should rollback changes on concurrency error" do
72
+ begin
73
+ persistence.commit create_commit(id, 3, {"foo" => "first"}, {"foo" => "second"}, {"foo" => "third"})
74
+ rescue Eventus::ConcurrencyError
75
+ end
76
+
77
+ result = persistence.load id
78
+ result.length.should == 20
79
+ end
80
+
81
+ it "should load all events from a minimum" do
82
+ result = persistence.load id, 10
83
+ result.length.should == 11
84
+ end
85
+ end
86
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'delegate'
1
2
  require 'rubygems'
2
3
  require 'bundler/setup'
3
4
 
@@ -8,8 +9,15 @@ Bundler.require :development
8
9
 
9
10
  Dir[File.join(File.dirname(__FILE__), 'support', '*.rb')].each { |d| require d }
10
11
  MONGO_URI = ENV['MONGO_URI'] || 'mongodb://localhost/test'
12
+ SEQUEL_URI = ENV['SEQUEL_URI'] || 'sqlite:///'
13
+ db = Sequel.connect SEQUEL_URI
14
+ db.extension :sqlite_json
15
+ Sequel.database_timezone = :utc
16
+ Eventus::Persistence::Sequel.migrate!(db)
17
+
11
18
 
12
19
  RSpec.configure do |config|
20
+ config.backtrace_exclusion_patterns = []
13
21
  config.mock_with :rspec
14
22
  end
15
23
 
metadata CHANGED
@@ -1,15 +1,155 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Staten
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-22 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2014-12-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: uuid
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mongo
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bson_ext
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: redis
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: kyotocabinet-ruby
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sequel
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: sqlite3
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sequel-enhancements
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
13
153
  description: An Event Store
14
154
  email:
15
155
  - jstaten07@gmail.com
@@ -35,6 +175,8 @@ files:
35
175
  - lib/eventus/persistence/kyotocabinet.rb
36
176
  - lib/eventus/persistence/mongo.rb
37
177
  - lib/eventus/persistence/redis.rb
178
+ - lib/eventus/persistence/sequel.rb
179
+ - lib/eventus/persistence/sequel/migrations/01_eventus_commits.rb
38
180
  - lib/eventus/serializers.rb
39
181
  - lib/eventus/serializers/marshal.rb
40
182
  - lib/eventus/serializers/msgpack.rb
@@ -47,6 +189,7 @@ files:
47
189
  - spec/persistence/kyotocabinet_spec.rb
48
190
  - spec/persistence/mongo_spec.rb
49
191
  - spec/persistence/redis_spec.rb
192
+ - spec/persistence/sequel_spec.rb
50
193
  - spec/spec_helper.rb
51
194
  - spec/stream_spec.rb
52
195
  homepage: ''
@@ -80,5 +223,6 @@ test_files:
80
223
  - spec/persistence/kyotocabinet_spec.rb
81
224
  - spec/persistence/mongo_spec.rb
82
225
  - spec/persistence/redis_spec.rb
226
+ - spec/persistence/sequel_spec.rb
83
227
  - spec/spec_helper.rb
84
228
  - spec/stream_spec.rb