active_domain 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 74c4d087cd860f21a6a06dc4cdf92b83d548d110
4
+ data.tar.gz: 6ebb39922facc4a7206de29e81988162fb90dcac
5
+ SHA512:
6
+ metadata.gz: 5edbadc45fbabb5483243f3a6ee77b920464b68f3a8e1c24e2efff832b6b2c53e63f96b81d41db53b9a43517256c1c2067220c098d6e8fa11e88e43c4073022b
7
+ data.tar.gz: 1520d8f34006d2ec112637541f029c5d7fff16072f2e6412d0190480dde1dbc0e8f9a73d3ffbe5e2a896eadfb0c1b5fcdae302a055ead1e7a79581656825a582
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Andreas Reischuck
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # Activeevent
2
+
3
+ TODO: Write a gem description
@@ -0,0 +1,10 @@
1
+ module ActiveDomain
2
+ class Event < ActiveEvent::Event
3
+ self.table_name = 'domain_events'
4
+
5
+ # allow write inside the domain
6
+ def readonly?
7
+ @readonly
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ module ActiveDomain
2
+ class EventRepository
3
+
4
+ def self.ordered
5
+ ActiveDomain::Event.order(:id)
6
+ end
7
+
8
+ def self.after_id(id)
9
+ ordered.where ActiveDomain::Event.arel_table['id'].gt(id)
10
+ end
11
+
12
+ def self.store(event)
13
+ stored_event = ActiveDomain::Event.create! event: event.class.name,
14
+ data: event,
15
+ created_at: DateTime.now
16
+ event.add_store_infos store_id: stored_event.id
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ require 'active_event'
2
+ require 'active_support/core_ext'
3
+ require 'active_domain/version'
4
+
5
+ module ActiveDomain
6
+ extend ActiveSupport::Autoload
7
+
8
+ autoload :Autoload
9
+ autoload :CommandProcessor
10
+ autoload :CommandRoutes
11
+ autoload :Projection
12
+ autoload :ProjectionRegistry
13
+ autoload :Server
14
+
15
+ autoload :Event, (File.expand_path '../../app/models/active_domain/event', __FILE__)
16
+ autoload :EventRepository, (File.expand_path '../../app/models/active_domain/event_repository',__FILE__)
17
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveDomain
2
+ module Autoload
3
+ def self.app_path=(path)
4
+ dirs = []
5
+ dirs << "#{path}/command_processors/**/*.rb"
6
+ dirs << "#{path}/validations/**/*.rb"
7
+ dirs << "#{path}/projections/**/*.rb"
8
+ dirs << "#{path}/models/**/*.rb"
9
+ ActiveEvent::Support::Autoloader.load_from dirs
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,40 @@
1
+ require 'drb/drb'
2
+
3
+ module ActiveDomain
4
+ module CommandProcessor
5
+ extend ActiveSupport::Concern
6
+ include DRb::DRbUndumped
7
+
8
+ module ClassMethods
9
+ protected
10
+
11
+ def process(clazz, method_name = nil, &block)
12
+ method_name ||= "process#{clazz.name.split('::').last}"
13
+ define_method(method_name, &block)
14
+ CommandRoutes.route clazz, self, method_name
15
+ end
16
+ end
17
+
18
+ protected
19
+
20
+ def event(event)
21
+ store event
22
+ publish event
23
+ invoke event
24
+ end
25
+
26
+ private
27
+
28
+ def invoke(event)
29
+ ProjectionRegistry.invoke event
30
+ end
31
+
32
+ def store(event)
33
+ EventRepository.store event
34
+ end
35
+
36
+ def publish(event)
37
+ ActiveEvent::EventServer.publish event
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ module ActiveDomain
2
+ class CommandRoutes
3
+ def version
4
+ '0.1.0'
5
+ end
6
+
7
+ def initialize
8
+ self.processors = {}
9
+ end
10
+
11
+ def run_command(command)
12
+ processor, method = @@routes[command.class]
13
+ processor_instance(processor).method(method).call(command)
14
+ end
15
+
16
+ def self.route(type, processor, method)
17
+ @@routes[type] = [processor, method]
18
+ end
19
+
20
+ private
21
+
22
+ attr_accessor :processors
23
+
24
+ def processor_instance(processor)
25
+ processors[processor] ||= processor.new
26
+ end
27
+
28
+ @@routes = {}
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module ActiveDomain
2
+ module Projection
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ ProjectionRegistry::register(self)
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,48 @@
1
+ require 'singleton'
2
+
3
+ module ActiveDomain
4
+ class TooManyArgumentsError < StandardError
5
+ end
6
+
7
+ class ProjectionRegistry
8
+ include Singleton
9
+
10
+ def self.register(event_handler)
11
+ self.registry << event_handler
12
+ end
13
+
14
+ def self.invoke(event)
15
+ instance.invoke event
16
+ end
17
+
18
+ def invoke(event)
19
+ event_type = event.class.name.split('::').last.to_sym
20
+ return unless handlers.has_key? event_type
21
+ handlers[event_type].each do |handler_method|
22
+ handler_method.owner.new.send handler_method.name, event
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ cattr_accessor :registry
29
+ attr_accessor :handlers
30
+
31
+ def initialize
32
+ self.handlers = Hash.new do |hash, key|
33
+ hash[key] = []
34
+ end
35
+ self.class.registry.freeze.each do |handler|
36
+ handler.public_instance_methods(false).each do |method_name|
37
+ method = handler.instance_method method_name
38
+ event_type = method_name.to_s.camelcase.to_sym
39
+ raise TooManyArgumentsError if 1 != method.arity
40
+ handlers[event_type] << method
41
+ end
42
+ end
43
+ handlers.freeze
44
+ end
45
+
46
+ self.registry = []
47
+ end
48
+ end
@@ -0,0 +1,74 @@
1
+ require 'active_record'
2
+ require 'drb/drb'
3
+
4
+ module ActiveDomain
5
+ class Server
6
+
7
+ def self.run(options = nil)
8
+ self.new(options).run
9
+ end
10
+
11
+ def initialize(new_options = nil)
12
+ self.options = new_options.deep_symbolize_keys! unless new_options.nil?
13
+ end
14
+
15
+ def run
16
+ ActiveEvent::ValidationsRegistry.build
17
+ ActiveRecord::Base.establish_connection options[:domain_database]
18
+ ActiveEvent::EventServer.start options
19
+ drb_uri = URI::Generic.build(options[:drb_server]).to_s
20
+ DRb.start_service(drb_uri, domain)
21
+ DRb.thread.join
22
+ end
23
+
24
+ def env
25
+ @env = ENV['DOMAIN_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
26
+ end
27
+
28
+ def options
29
+ @options ||= parse_options(ARGV)
30
+ end
31
+
32
+ def domain
33
+ @domain ||= ActiveDomain::CommandRoutes.new
34
+ end
35
+
36
+ cattr_accessor :base_path
37
+ cattr_accessor :config_file
38
+
39
+ def config_file
40
+ self.class.config_file || File.expand_path('config/disco.yml', base_path)
41
+ end
42
+
43
+ private
44
+
45
+ attr_writer :options
46
+ attr_writer :domain
47
+
48
+ def default_options
49
+ {
50
+ drb_server: {
51
+ scheme: 'druby',
52
+ hostname: '127.0.0.1',
53
+ port: 8787,
54
+ },
55
+ domain_database: {
56
+ adapter: 'sqlite3',
57
+ database: File.expand_path('db/domain.sqlite3', base_path)
58
+ },
59
+ event_connection: {
60
+ scheme: 'amqp',
61
+ userinfo: nil,
62
+ host: '127.0.0.1',
63
+ port: 9797,
64
+ },
65
+ event_exchange: 'events'
66
+ }
67
+ end
68
+
69
+ def parse_options(args)
70
+ options = default_options
71
+ options.merge! YAML.load_file(config_file)[env].deep_symbolize_keys! unless config_file.blank?
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,11 @@
1
+ module ActiveDomain
2
+ # Returns the version of the currently loaded ActiveDomain as a Gem::Version
3
+ def self.version
4
+ Gem::Version.new '0.1.0'
5
+ end
6
+
7
+ module VERSION #:nodoc:
8
+ MAJOR, MINOR, TINY, PRE = ActiveDomain.version.segments
9
+ STRING = ActiveDomain.version.to_s
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe ActiveDomain::CommandProcessor do
4
+ class TestDummy
5
+ end
6
+ class TestDummyProcessor
7
+ include ActiveDomain::CommandProcessor
8
+
9
+ process TestDummy do |cmd|
10
+ event cmd
11
+ end
12
+ end
13
+
14
+ describe 'class helper' do
15
+ it 'define event process' do
16
+ TestDummyProcessor.instance_method(:processTestDummy).should be
17
+ end
18
+ end
19
+
20
+ describe 'instance' do
21
+ it 'allows event method' do
22
+ magic_number = 42
23
+ expect(ActiveDomain::ProjectionRegistry).to receive(:invoke).with(magic_number)
24
+ expect(ActiveDomain::EventRepository).to receive(:store).with(magic_number)
25
+ expect(ActiveEvent::EventServer).to receive(:publish).with(magic_number)
26
+ TestDummyProcessor.new.processTestDummy magic_number
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe ActiveDomain::ProjectionRegistry do
4
+ class TestEvent
5
+ end
6
+ class TestProjection
7
+ def test_event(event)
8
+ end
9
+ def dummy_event(event)
10
+ end
11
+ end
12
+ before :all do
13
+ ActiveDomain::ProjectionRegistry.register(TestProjection)
14
+ end
15
+
16
+ it 'initializes' do
17
+ ActiveDomain::ProjectionRegistry.instance.should be
18
+ end
19
+
20
+ it 'invokes event handlers' do
21
+ event = TestEvent.new
22
+ expect_any_instance_of(TestProjection).to receive(:test_event).with(event)
23
+ ActiveDomain::ProjectionRegistry.invoke(event)
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe ActiveDomain::Projection do
4
+ it 'should register automatically' do
5
+ expect(ActiveDomain::ProjectionRegistry).to receive(:register) do |arg|
6
+ arg.name.to_sym.should eq :TestProjection
7
+ end
8
+ class TestProjection
9
+ include ActiveDomain::Projection
10
+ end
11
+ end
12
+ end
@@ -0,0 +1 @@
1
+ require 'active_domain'
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_domain
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andreas Reischuck
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: active_event
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>'
32
+ - !ruby/object:Gem::Version
33
+ version: 3.2.0
34
+ - - <
35
+ - !ruby/object:Gem::Version
36
+ version: 4.1.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - '>'
42
+ - !ruby/object:Gem::Version
43
+ version: 3.2.0
44
+ - - <
45
+ - !ruby/object:Gem::Version
46
+ version: 4.1.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: activemodel
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - '>'
52
+ - !ruby/object:Gem::Version
53
+ version: 3.2.0
54
+ - - <
55
+ - !ruby/object:Gem::Version
56
+ version: 4.1.0
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>'
62
+ - !ruby/object:Gem::Version
63
+ version: 3.2.0
64
+ - - <
65
+ - !ruby/object:Gem::Version
66
+ version: 4.1.0
67
+ - !ruby/object:Gem::Dependency
68
+ name: bunny
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :runtime
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: bundler
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: '1.3'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ~>
93
+ - !ruby/object:Gem::Version
94
+ version: '1.3'
95
+ - !ruby/object:Gem::Dependency
96
+ name: rake
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ - !ruby/object:Gem::Dependency
110
+ name: rspec
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ description: Domain server, Command processors and routes for rails-disco
124
+ email: andreas.reischuck@hicknhack-software.com
125
+ executables: []
126
+ extensions: []
127
+ extra_rdoc_files: []
128
+ files:
129
+ - app/models/active_domain/event.rb
130
+ - app/models/active_domain/event_repository.rb
131
+ - lib/active_domain/autoload.rb
132
+ - lib/active_domain/command_processor.rb
133
+ - lib/active_domain/command_routes.rb
134
+ - lib/active_domain/projection.rb
135
+ - lib/active_domain/projection_registry.rb
136
+ - lib/active_domain/server.rb
137
+ - lib/active_domain/version.rb
138
+ - lib/active_domain.rb
139
+ - README.md
140
+ - MIT-LICENSE
141
+ - spec/lib/command_processor_spec.rb
142
+ - spec/lib/projection_registry_spec.rb
143
+ - spec/lib/projection_spec.rb
144
+ - spec/spec_helper.rb
145
+ homepage: https://github.com/hicknhack-software/rails-disco
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - '>='
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.0.5
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: Domain related stuff (part of rails-disco)
169
+ test_files:
170
+ - spec/lib/command_processor_spec.rb
171
+ - spec/lib/projection_registry_spec.rb
172
+ - spec/lib/projection_spec.rb
173
+ - spec/spec_helper.rb