ruby_event_store 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b20c0b1993fd1f71772a7963b630a711184bdfe2
4
+ data.tar.gz: 76fbda0433d8411362b2bb7a9352bb2771662928
5
+ SHA512:
6
+ metadata.gz: 32aa8a98da6beb67d3c8e7814eb27d7460672db707ee71a5e85392e63a237ac149da7785692211b01ce66a84a78d3f562193c0bba7b842092ee4f9b65deed6f6
7
+ data.tar.gz: d29d1fc35b3fd86c1951aae3639bf946c59353d5646e2fe98945077aa101662cf171e0f2d665d24230ee758a04d9e05fd7f2a73d73c169b8ce62395c229cfce9
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.5
4
+ before_install: gem install bundler
5
+ gemfile: Gemfile
6
+ script: bundle exec mutant --include lib --require ruby_event_store --use rspec "RubyEventStore*"
7
+ notifications:
8
+ slack:
9
+ secure: qCcGv1MmryEhPoHzTvZvgSv21UcC7j2Cfq0b0hmQWuYHrHN+jhqjhg7PuElNyr0mk6N1acIcVqOAWpS20ZkG/mipW2RBBXVEc9zVR10pvJnlKDmGKd4Vmj394VgIknn8ciruglw1LoJManf1bV7/Wm4ITMt3zCQqTMGclRUqA0l/dzK2z9zU35cT4v38nTGnoGVrPQx29FvpU3J/h9qC6kGllw3Bkic2nmpFABYOI49LQFF3/vdrbnK3Zo1rudHMV0lNoPg5Ntrbd6XHXUKrBGBcZmGSh3wW/mfYf9Tcft+5MwtCu4b70KnFknx7oFmBlU8JFYg2x5f1xNSIoRkDmLI5/jNDWJ3oLAtYjgY5CdBMlxnhhfnCBmbaxEJhTuscm2sIp+S+4+ggm8x/daIK3BUaBAV5BT8An52BXhQ/F6cdnYiSVn+5lGap/1wF2TWwnN/oVc+JVfATouG9FCygzMekUaji94JMKBtS+QgoLdAE5ufEGBeDONJELRD8Lca1R4uWSg2snf93GWoONca9aJfkIfXj3m+VaoAM9Bq9DGcOXwZESkltE2E+31Fznh5qYCRH1zgtgB0Hx8x7sdaxNQyybvgNS1R0lGnIU/NrUmREcUi5BYEI5YqygBtkTZ7F/nlYQgydKjjHJ6FG3oLc3ggxffE8oAdpuxvlUQ8ZN6o=
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby_event_store.gemspec
4
+ gemspec
@@ -0,0 +1 @@
1
+ # ruby_event_store
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,11 @@
1
+ require 'ruby_event_store/actions/append_event_to_stream'
2
+ require 'ruby_event_store/actions/read_all_events'
3
+ require 'ruby_event_store/actions/read_events_batch'
4
+ require 'ruby_event_store/actions/delete_stream_events'
5
+ require 'ruby_event_store/actions/read_all_streams'
6
+ require 'ruby_event_store/pub_sub/broker'
7
+ require 'ruby_event_store/errors'
8
+ require 'ruby_event_store/constants'
9
+ require 'ruby_event_store/facade'
10
+ require 'ruby_event_store/event'
11
+ require 'ruby_event_store/version'
@@ -0,0 +1,33 @@
1
+ module RubyEventStore
2
+ module Actions
3
+ class AppendEventToStream
4
+
5
+ def initialize(repository)
6
+ @repository = repository
7
+ end
8
+
9
+ def call(stream_name, event, expected_version)
10
+ raise WrongExpectedEventVersion if version_incorrect?(stream_name, expected_version)
11
+ save_event(event, stream_name)
12
+ event
13
+ end
14
+
15
+ private
16
+ attr_reader :repository
17
+
18
+ def version_incorrect?(stream_name, expected_version)
19
+ unless expected_version.nil?
20
+ find_last_event_version(stream_name) != expected_version
21
+ end
22
+ end
23
+
24
+ def find_last_event_version(stream_name)
25
+ repository.last_stream_event(stream_name).event_id
26
+ end
27
+
28
+ def save_event(event, stream_name)
29
+ repository.create(event.to_h.merge!(stream: stream_name))
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module RubyEventStore
2
+ module Actions
3
+ class DeleteStreamEvents
4
+
5
+ def initialize(repository)
6
+ @repository = repository
7
+ end
8
+
9
+ def call(stream_name)
10
+ raise IncorrectStreamData if stream_name.nil? || stream_name.empty?
11
+ delete_stream(stream_name)
12
+ end
13
+
14
+ private
15
+ attr_reader :repository
16
+
17
+ def delete_stream(stream_name)
18
+ repository.delete({stream: stream_name})
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,22 @@
1
+ module RubyEventStore
2
+ module Actions
3
+ class ReadAllEvents
4
+
5
+ def initialize(repository)
6
+ @repository = repository
7
+ end
8
+
9
+ def call(stream_name)
10
+ raise IncorrectStreamData if stream_name.nil? || stream_name.empty?
11
+ get_all_events(stream_name)
12
+ end
13
+
14
+ private
15
+ attr_reader :repository
16
+
17
+ def get_all_events(stream_name)
18
+ repository.load_all_events_forward(stream_name)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module RubyEventStore
2
+ module Actions
3
+ class ReadAllStreams
4
+
5
+ def initialize(repository)
6
+ @repository = repository
7
+ end
8
+
9
+ def call
10
+ get_all_events.group_by { |event| event.stream }
11
+ end
12
+
13
+ private
14
+ attr_reader :repository
15
+
16
+ def get_all_events
17
+ repository.get_all_events
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module RubyEventStore
2
+ module Actions
3
+ class ReadEventsBatch
4
+
5
+ def initialize(repository)
6
+ @repository = repository
7
+ end
8
+
9
+ def call(stream_name, start, count)
10
+ raise IncorrectStreamData if stream_name.nil? || stream_name.empty?
11
+ event = find_event(start)
12
+ get_events_batch(stream_name, event.id, count)
13
+ end
14
+
15
+ private
16
+ attr_reader :repository
17
+
18
+ def get_events_batch(stream_name, start, count)
19
+ repository.load_events_batch(stream_name, start, count)
20
+ end
21
+
22
+ def find_event(start)
23
+ event = repository.find({event_id: start})
24
+ raise EventNotFound if event.nil?
25
+ event
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module RubyEventStore
2
+ GLOBAL_STREAM = 'all'.freeze
3
+ end
@@ -0,0 +1,7 @@
1
+ module RubyEventStore
2
+ WrongExpectedEventVersion = Class.new(StandardError)
3
+ IncorrectStreamData = Class.new(StandardError)
4
+ EventNotFound = Class.new(StandardError)
5
+ SubscriberNotExist = Class.new(StandardError)
6
+ MethodNotDefined = Class.new(StandardError)
7
+ end
@@ -0,0 +1,37 @@
1
+ require 'securerandom'
2
+
3
+ module RubyEventStore
4
+ class Event
5
+
6
+ def initialize(event_data={})
7
+ @event_type = event_data.fetch(:event_type, event_name)
8
+ @event_id = event_data.fetch(:event_id, generate_id).to_s
9
+ @metadata = event_data.fetch(:metadata, {})
10
+ @data = event_data.fetch(:data, {})
11
+ end
12
+ attr_reader :event_type, :event_id, :metadata, :data
13
+
14
+ def to_h
15
+ {
16
+ event_type: event_type,
17
+ event_id: event_id,
18
+ metadata: metadata.merge!(publish_time),
19
+ data: data
20
+ }
21
+ end
22
+
23
+ private
24
+
25
+ def publish_time
26
+ { published_at: Time.now.utc }
27
+ end
28
+
29
+ def generate_id
30
+ SecureRandom.uuid
31
+ end
32
+
33
+ def event_name
34
+ self.class.name
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,64 @@
1
+ module RubyEventStore
2
+ class Facade
3
+
4
+ def initialize(repository)
5
+ @repository = repository
6
+ end
7
+ attr_reader :repository
8
+
9
+ def publish_event(event_data, stream_name = GLOBAL_STREAM, expected_version = nil)
10
+ append_event_to_stream(event_data, stream_name, expected_version)
11
+ end
12
+
13
+ def delete_stream(stream_name)
14
+ delete_stream_events(stream_name)
15
+ end
16
+
17
+ def read_events(stream_name, start, count)
18
+ read_events_batch(stream_name, start, count)
19
+ end
20
+
21
+ def read_all_events(stream_name)
22
+ read_all_stream_events(stream_name)
23
+ end
24
+
25
+ def read_all_streams
26
+ read_all_events_from_store
27
+ end
28
+
29
+ def subscribe(subscriber, event_types)
30
+ event_broker.add_subscriber(subscriber, event_types)
31
+ end
32
+
33
+ def subscribe_to_all_events(subscriber)
34
+ event_broker.add_global_subscriber(subscriber)
35
+ end
36
+
37
+ private
38
+
39
+ def append_event_to_stream(event_data, stream_name, expected_version)
40
+ event = Actions::AppendEventToStream.new(repository).call(stream_name, event_data, expected_version)
41
+ event_broker.notify_subscribers(event)
42
+ end
43
+
44
+ def delete_stream_events(stream_name)
45
+ Actions::DeleteStreamEvents.new(repository).call(stream_name)
46
+ end
47
+
48
+ def read_events_batch(stream_name, start, count)
49
+ Actions::ReadEventsBatch.new(repository).call(stream_name, start, count)
50
+ end
51
+
52
+ def read_all_stream_events(stream_name)
53
+ Actions::ReadAllEvents.new(repository).call(stream_name)
54
+ end
55
+
56
+ def read_all_events_from_store
57
+ Actions::ReadAllStreams.new(repository).call
58
+ end
59
+
60
+ def event_broker
61
+ @event_broker ||= PubSub::Broker.new
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,45 @@
1
+ module RubyEventStore
2
+ module PubSub
3
+ class Broker
4
+
5
+ def initialize
6
+ @subscribers = Hash.new {|hsh, key| hsh[key] = [] }
7
+ @global_subscribers = []
8
+ end
9
+
10
+ def add_subscriber(subscriber, event_types)
11
+ verify_subscriber(subscriber)
12
+ subscribe(subscriber, event_types)
13
+ end
14
+
15
+ def add_global_subscriber(subscriber)
16
+ verify_subscriber(subscriber)
17
+ @global_subscribers << subscriber
18
+ end
19
+
20
+ def notify_subscribers(event)
21
+ all_subscribers_for(event.event_type).each do |subscriber|
22
+ subscriber.handle_event(event)
23
+ end
24
+ end
25
+
26
+ private
27
+ attr_reader :subscribers
28
+
29
+ def verify_subscriber(subscriber)
30
+ raise SubscriberNotExist if subscriber.nil?
31
+ raise MethodNotDefined unless subscriber.methods.include? :handle_event
32
+ end
33
+
34
+ def subscribe(subscriber, event_types)
35
+ event_types.each do |type|
36
+ subscribers[type] << subscriber
37
+ end
38
+ end
39
+
40
+ def all_subscribers_for(event_type)
41
+ subscribers[event_type] + @global_subscribers
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module RubyEventStore
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ruby_event_store/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ruby_event_store"
8
+ spec.version = RubyEventStore::VERSION
9
+ spec.authors = ["rybex"]
10
+ spec.email = ["tomek.rybka@gmail.com"]
11
+
12
+ spec.summary = %q{Implementation of Event Store in Ruby}
13
+ spec.description = %q{Implementation of Event Store in Ruby}
14
+ spec.homepage = ''
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.8"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'pry'
25
+ spec.add_development_dependency 'mutant', '~> 0.7.8'
26
+ spec.add_development_dependency 'mutant-rspec', '~> 0.7.8'
27
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_event_store
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - rybex
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
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: pry
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: mutant
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.7.8
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.7.8
83
+ - !ruby/object:Gem::Dependency
84
+ name: mutant-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.7.8
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.7.8
97
+ description: Implementation of Event Store in Ruby
98
+ email:
99
+ - tomek.rybka@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - README.md
108
+ - Rakefile
109
+ - lib/ruby_event_store.rb
110
+ - lib/ruby_event_store/actions/append_event_to_stream.rb
111
+ - lib/ruby_event_store/actions/delete_stream_events.rb
112
+ - lib/ruby_event_store/actions/read_all_events.rb
113
+ - lib/ruby_event_store/actions/read_all_streams.rb
114
+ - lib/ruby_event_store/actions/read_events_batch.rb
115
+ - lib/ruby_event_store/constants.rb
116
+ - lib/ruby_event_store/errors.rb
117
+ - lib/ruby_event_store/event.rb
118
+ - lib/ruby_event_store/facade.rb
119
+ - lib/ruby_event_store/pub_sub/broker.rb
120
+ - lib/ruby_event_store/version.rb
121
+ - ruby_event_store.gemspec
122
+ homepage: ''
123
+ licenses: []
124
+ metadata: {}
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.4.3
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: Implementation of Event Store in Ruby
145
+ test_files: []