active_projection 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,90 +1,91 @@
1
- module ActiveProjection
2
- module ProjectionType
3
- extend ActiveSupport::Concern
4
- class WrongArgumentsCountError < StandardError
5
- end
6
- included do
7
- ProjectionTypeRegistry::register(self)
8
- end
9
-
10
- def initialize
11
- self.handlers = Hash.new do |hash, key|
12
- hash[key] = []
13
- end
14
- self.class.public_instance_methods(false).each do |method_name|
15
- method = self.class.instance_method method_name
16
- raise WrongArgumentsCountError if 2 < method.arity or method.arity < 1
17
- event_type = ProjectionType.method_name_to_event_type method_name
18
- handlers[event_type] << [method_name, method.arity]
19
- end
20
- end
21
-
22
- def evaluate(headers)
23
- unless solid?
24
- LOGGER.error "[#{self.class.name}] is broken"
25
- return false
26
- end
27
- last_id = fetch_last_id
28
- event_id = headers[:id]
29
- case
30
- when last_id + 1 == event_id
31
- true
32
- when last_id >= event_id
33
- LOGGER.debug "[#{self.class.name}]: event #{event_id} already processed"
34
- false
35
- when last_id < event_id
36
- set_broken
37
- LOGGER.error "[#{self.class.name}]: #{event_id - last_id} events are missing"
38
- false
39
- end
40
- end
41
-
42
- def invoke(event, headers)
43
- event_id = headers[:id]
44
- event_type = event.class.name.to_sym
45
- handlers[event_type].each do |method, arity|
46
- begin
47
- if 1 == arity
48
- self.send method, event
49
- else
50
- self.send method, event, headers
51
- end
52
- rescue Exception => e
53
- LOGGER.error "[#{self.class.name}]: error processing #{event_type}[#{event_id}]\n#{e.message}\n#{e.backtrace}"
54
- set_broken
55
- raise
56
- end
57
- end
58
- update_last_id event_id
59
- LOGGER.debug "[#{self.class.name}]: successfully processed #{event_type}[#{event_id}]"
60
- end
61
-
62
- private
63
- attr_accessor :handlers
64
- attr_writer :projection_id
65
-
66
- def self.method_name_to_event_type(method_name)
67
- method_name.to_s.gsub('__', '/').camelcase.to_sym
68
- end
69
-
70
- def projection_id
71
- @projection_id ||= ProjectionRepository.ensure_exists(self.class.name).id
72
- end
73
-
74
- def solid?
75
- ProjectionRepository.solid? projection_id
76
- end
77
-
78
- def fetch_last_id
79
- ProjectionRepository.get_last_id projection_id
80
- end
81
-
82
- def set_broken
83
- ProjectionRepository.set_broken projection_id
84
- end
85
-
86
- def update_last_id(id)
87
- ProjectionRepository.set_last_id projection_id, id
88
- end
89
- end
90
- end
1
+ module ActiveProjection
2
+ module ProjectionType
3
+ extend ActiveSupport::Concern
4
+ class WrongArgumentsCountError < StandardError
5
+ end
6
+ included do
7
+ ProjectionTypeRegistry.register(self)
8
+ end
9
+
10
+ def initialize
11
+ self.handlers = Hash.new do |hash, key|
12
+ hash[key] = []
13
+ end
14
+ self.class.public_instance_methods(false).each do |method_name|
15
+ method = self.class.instance_method method_name
16
+ fail WrongArgumentsCountError if 2 < method.arity || method.arity < 1
17
+ event_type = ProjectionType.method_name_to_event_type method_name
18
+ handlers[event_type] << [method_name, method.arity]
19
+ end
20
+ end
21
+
22
+ def evaluate(headers)
23
+ unless solid?
24
+ LOGGER.error "[#{self.class.name}] is broken"
25
+ return false
26
+ end
27
+ last_id = fetch_last_id
28
+ event_id = headers[:id]
29
+ case
30
+ when last_id + 1 == event_id
31
+ true
32
+ when last_id >= event_id
33
+ LOGGER.debug "[#{self.class.name}]: event #{event_id} already processed"
34
+ false
35
+ when last_id < event_id
36
+ mark_broken
37
+ LOGGER.error "[#{self.class.name}]: #{event_id - last_id} events are missing"
38
+ false
39
+ end
40
+ end
41
+
42
+ def invoke(event, headers)
43
+ event_id = headers[:id]
44
+ event_type = event.class.name.to_sym
45
+ handlers[event_type].each do |method, arity|
46
+ begin
47
+ if 1 == arity
48
+ send method, event
49
+ else
50
+ send method, event, headers
51
+ end
52
+ rescue => e
53
+ LOGGER.error "[#{self.class.name}]: error processing #{event_type}[#{event_id}]\n#{e.message}\n#{e.backtrace}"
54
+ mark_broken
55
+ raise
56
+ end
57
+ end
58
+ update_last_id event_id
59
+ LOGGER.debug "[#{self.class.name}]: successfully processed #{event_type}[#{event_id}]"
60
+ end
61
+
62
+ private
63
+
64
+ attr_accessor :handlers
65
+ attr_writer :projection_id
66
+
67
+ def self.method_name_to_event_type(method_name)
68
+ method_name.to_s.gsub('__', '/').camelcase.to_sym
69
+ end
70
+
71
+ def projection_id
72
+ @projection_id ||= ProjectionRepository.ensure_exists(self.class.name).id
73
+ end
74
+
75
+ def solid?
76
+ ProjectionRepository.solid? projection_id
77
+ end
78
+
79
+ def fetch_last_id
80
+ ProjectionRepository.last_id projection_id
81
+ end
82
+
83
+ def mark_broken
84
+ ProjectionRepository.mark_broken projection_id
85
+ end
86
+
87
+ def update_last_id(id)
88
+ ProjectionRepository.set_last_id projection_id, id
89
+ end
90
+ end
91
+ end
@@ -1,28 +1,26 @@
1
- require 'singleton'
2
-
3
- module ActiveProjection
4
- class ProjectionTypeRegistry
5
- include Singleton
6
-
7
- # register a new projection class
8
- #
9
- # The best way to create a new projection is using the ProjectionType module
10
- # This module automatically registers each class
11
- def self.register(projection)
12
- self.registry << projection
13
- end
14
-
15
- # @return an enumerable with all projections
16
- def self.projections
17
- instance.projections.each
18
- end
19
-
20
- def projections
21
- @projections ||= self.class.registry.freeze.map { |projection_class| projection_class.new }.freeze
22
- end
23
-
24
- private
25
-
26
- cattr_accessor(:registry) { [] }
27
- end
28
- end
1
+ require 'singleton'
2
+
3
+ module ActiveProjection
4
+ class ProjectionTypeRegistry
5
+ include Singleton
6
+
7
+ # register a new projection class
8
+ #
9
+ # The best way to create a new projection is using the ProjectionType module
10
+ # This module automatically registers each class
11
+ def self.register(projection)
12
+ registry << projection
13
+ end
14
+
15
+ # @return an enumerable with all projections
16
+ def self.projections
17
+ instance.projections.each
18
+ end
19
+
20
+ def projections
21
+ @projections ||= self.class.registry.freeze.map { |projection_class| projection_class.new }.freeze
22
+ end
23
+
24
+ cattr_accessor(:registry) { [] }
25
+ end
26
+ end
@@ -1,8 +1,8 @@
1
- require 'active_projection'
2
- require 'rails'
3
-
4
- module ActiveProjection
5
- class Railtie < Rails::Railtie # :nodoc:
6
- config.eager_load_namespaces << ActiveProjection
7
- end
8
- end
1
+ require 'active_projection'
2
+ require 'rails'
3
+
4
+ module ActiveProjection
5
+ class Railtie < Rails::Railtie # :nodoc:
6
+ config.eager_load_namespaces << ActiveProjection
7
+ end
8
+ end
@@ -1,66 +1,65 @@
1
- require 'active_record'
2
-
3
- module ActiveProjection
4
- class Server
5
-
6
- def self.run(options = nil)
7
- self.new(options).run
8
- end
9
-
10
- def initialize(new_options = nil)
11
- self.options = new_options.deep_symbolize_keys! unless new_options.nil?
12
- end
13
-
14
- def run
15
- EventClient.start options
16
- end
17
-
18
- def env
19
- @env = ENV['PROJECTION_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
20
- end
21
-
22
- def options
23
- @options ||= parse_options(ARGV)
24
- end
25
-
26
- cattr_accessor :base_path
27
- cattr_accessor :config_file
28
- cattr_accessor :rails_config_file
29
-
30
- def config_file
31
- self.class.config_file ||= File.expand_path('config/disco.yml', base_path)
32
- end
33
-
34
- def rails_config_file
35
- self.class.rails_config_file ||= File.expand_path('config/database.yml', base_path)
36
- end
37
-
38
- private
39
-
40
- attr_writer :options
41
- attr_writer :domain
42
-
43
- def default_options
44
- {
45
- projection_database: {
46
- adapter: 'sqlite3',
47
- database: File.expand_path('db/production.sqlite3', base_path)
48
- },
49
- event_connection: {
50
- scheme: 'amqp',
51
- userinfo: nil,
52
- host: '127.0.0.1',
53
- port: 9797,
54
- },
55
- event_exchange: 'events'
56
- }
57
- end
58
-
59
- def parse_options(args)
60
- options = default_options
61
- options.merge! YAML.load_file(config_file)[env].deep_symbolize_keys! unless config_file.blank?
62
- options[:projection_database] = YAML.load_file(rails_config_file)[env].deep_symbolize_keys! unless rails_config_file.blank?
63
- options
64
- end
65
- end
66
- end
1
+ require 'active_record'
2
+
3
+ module ActiveProjection
4
+ class Server
5
+ def self.run(options = nil)
6
+ new(options).run
7
+ end
8
+
9
+ def initialize(new_options = nil)
10
+ self.options = new_options.deep_symbolize_keys! unless new_options.nil?
11
+ end
12
+
13
+ def run
14
+ EventClient.start options
15
+ end
16
+
17
+ def env
18
+ @env = ENV['PROJECTION_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
19
+ end
20
+
21
+ def options
22
+ @options ||= parse_options(ARGV)
23
+ end
24
+
25
+ cattr_accessor :base_path
26
+ cattr_accessor :config_file
27
+ cattr_accessor :rails_config_file
28
+
29
+ def config_file
30
+ self.class.config_file ||= File.expand_path('config/disco.yml', base_path)
31
+ end
32
+
33
+ def rails_config_file
34
+ self.class.rails_config_file ||= File.expand_path('config/database.yml', base_path)
35
+ end
36
+
37
+ private
38
+
39
+ attr_writer :options
40
+ attr_writer :domain
41
+
42
+ def default_options
43
+ {
44
+ projection_database: {
45
+ adapter: 'sqlite3',
46
+ database: File.expand_path('db/production.sqlite3', base_path),
47
+ },
48
+ event_connection: {
49
+ scheme: 'amqp',
50
+ userinfo: nil,
51
+ host: '127.0.0.1',
52
+ port: 9797,
53
+ },
54
+ event_exchange: 'events',
55
+ }
56
+ end
57
+
58
+ def parse_options(_args)
59
+ options = default_options
60
+ options.merge! YAML.load_file(config_file)[env].deep_symbolize_keys! unless config_file.blank?
61
+ options[:projection_database] = YAML.load_file(rails_config_file)[env].deep_symbolize_keys! unless rails_config_file.blank?
62
+ options
63
+ end
64
+ end
65
+ end
@@ -1,7 +1,7 @@
1
1
  module ActiveProjection
2
2
  # Returns the version of the currently loaded ActiveProjection as a Gem::Version
3
3
  def self.version
4
- Gem::Version.new '0.5.2'
4
+ Gem::Version.new '0.5.3'
5
5
  end
6
6
 
7
7
  module VERSION #:nodoc:
@@ -1,8 +1,8 @@
1
- require 'factory_girl'
2
-
3
- FactoryGirl.define do
4
- factory :projection, class: ActiveProjection::Projection do
5
- last_id 4
6
- solid true
7
- end
8
- end
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :projection, class: ActiveProjection::Projection do
5
+ last_id 4
6
+ solid true
7
+ end
8
+ end
@@ -1,19 +1,19 @@
1
- require_relative '../spec_helper'
2
-
3
- describe ActiveProjection::ProjectionTypeRegistry do
4
- class TestEvent
5
- end
6
- class TestProjection
7
- end
8
- before :all do
9
- ActiveProjection::ProjectionTypeRegistry.register(TestProjection)
10
- end
11
-
12
- it 'initializes' do
13
- ActiveProjection::ProjectionTypeRegistry.instance.should be
14
- end
15
-
16
- it 'report projections' do
17
- ActiveProjection::ProjectionTypeRegistry.projections.count.should eq 1
18
- end
19
- end
1
+ require_relative '../spec_helper'
2
+
3
+ describe ActiveProjection::ProjectionTypeRegistry do
4
+ class TestEvent
5
+ end
6
+ class TestProjection
7
+ end
8
+ before :all do
9
+ ActiveProjection::ProjectionTypeRegistry.register(TestProjection)
10
+ end
11
+
12
+ it 'initializes' do
13
+ expect(ActiveProjection::ProjectionTypeRegistry.instance).to be
14
+ end
15
+
16
+ it 'report projections' do
17
+ expect(ActiveProjection::ProjectionTypeRegistry.projections.count).to eq(1)
18
+ end
19
+ end