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 +4 -4
- data/Gemfile +1 -12
- data/eventus.gemspec +11 -0
- data/lib/eventus/persistence/sequel/migrations/01_eventus_commits.rb +22 -0
- data/lib/eventus/persistence/sequel.rb +54 -0
- data/lib/eventus/persistence.rb +1 -0
- data/lib/eventus/version.rb +1 -1
- data/spec/persistence/sequel_spec.rb +86 -0
- data/spec/spec_helper.rb +8 -0
- metadata +147 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd0b08439ed10730278782f0c345e05ce2dfe151
|
4
|
+
data.tar.gz: ae83a990fd2d9d8bf2acaf17264517310a36a998
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 040f8cb4ba662af9899402fa9e865d03054a88ca4062a41c15e4a59e9be1964c309294cb00fdb6eee9cc54ba7b9064ede144fc13531aacac558c390cd88830f1
|
7
|
+
data.tar.gz: 1cb838126015dc629732c390f33646443580c718052257a7ab374784a4ee27be5e2c01b22e8e35854630674f4fbf8a31696465f23936cc01b313fcac04e97c54
|
data/Gemfile
CHANGED
@@ -1,14 +1,3 @@
|
|
1
|
-
source
|
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
|
data/lib/eventus/persistence.rb
CHANGED
data/lib/eventus/version.rb
CHANGED
@@ -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.
|
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-
|
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
|