active_projection 0.5.2 → 0.5.3

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.
@@ -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