active_projection 0.1.0 → 0.2.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 +4 -4
- data/app/models/active_projection/projection_repository.rb +2 -2
- data/lib/active_projection/autoload.rb +29 -7
- data/lib/active_projection/event_client.rb +64 -18
- data/lib/active_projection/projection_type.rb +1 -1
- data/lib/active_projection/version.rb +1 -1
- data/spec/models/projection_repository_spec.rb +4 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a021d20d944d3f69ff88671afb2b3dd63ad306b0
|
4
|
+
data.tar.gz: 648e52cba7a201f5bc37036c28ffedc742fa26bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16138af067df4265c38f11c20e6d7594893181c2e854079c52babeda32f0f3d3e70f3b3770e6eb281c713e13c80dba5dc1092657bf41279956dd4bcf369a3406
|
7
|
+
data.tar.gz: 9d6b556fb2014e0a26ecd8232fa710041c35a91362ba77bbc089c1cb3f8867e2d4194111b6b9f6dc598fec924f2464095577080fa46860f392d1261edb559199
|
@@ -1,20 +1,42 @@
|
|
1
1
|
module ActiveProjection
|
2
2
|
module Autoload
|
3
|
+
include ActiveEvent::Support::Autoload
|
4
|
+
private
|
5
|
+
def self.dir_names
|
6
|
+
%W(app/models)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.reload
|
10
|
+
ActiveEvent::Support::Autoloader.reload_from pdirs
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
3
14
|
def self.worker_config=(config)
|
4
|
-
|
5
|
-
|
15
|
+
set_pdirs config
|
16
|
+
ActiveEvent::Support::Autoloader.load_from pdirs
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.watchable_dirs
|
20
|
+
watchable_dirs = super
|
21
|
+
watchable_dirs['app/projections'] = [:rb]
|
22
|
+
watchable_dirs
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def self.set_pdirs(config)
|
27
|
+
@pdirs = []
|
28
|
+
projections_dir = "#{config[:path]}/app/projections/**/*.rb"
|
6
29
|
if config[:count] == 1
|
7
|
-
|
30
|
+
@pdirs << projections_dir
|
8
31
|
else
|
9
32
|
Dir[*projections_dir].each_with_index.map { |item, i| i % config[:count] == config[:number] ? item : nil }.compact.each do |dir|
|
10
|
-
|
33
|
+
@pdirs << dir
|
11
34
|
end
|
12
35
|
end
|
13
|
-
ActiveEvent::Support::Autoloader.load_from dirs
|
14
36
|
end
|
15
37
|
|
16
|
-
def self.
|
17
|
-
|
38
|
+
def self.pdirs
|
39
|
+
@pdirs ||= []
|
18
40
|
end
|
19
41
|
end
|
20
42
|
end
|
@@ -5,28 +5,71 @@ module ActiveProjection
|
|
5
5
|
include Singleton
|
6
6
|
|
7
7
|
def self.start(options)
|
8
|
-
instance.
|
8
|
+
instance.options = options
|
9
|
+
instance.start
|
9
10
|
end
|
10
11
|
|
11
|
-
def start
|
12
|
-
self.options = options
|
12
|
+
def start
|
13
13
|
event_connection.start
|
14
|
-
|
15
|
-
|
16
|
-
puts "Received #{properties.type} with #{body}"
|
17
|
-
ProjectionTypeRegistry.process(properties.headers.deep_symbolize_keys, Object.const_get(properties.type).new((JSON.parse body).deep_symbolize_keys))
|
18
|
-
end
|
19
|
-
rescue Interrupt => _
|
20
|
-
event_channel.close
|
21
|
-
event_connection.close
|
22
|
-
end
|
23
|
-
last_ids = ProjectionRepository.all.to_a.map { |p| p.last_id }
|
24
|
-
request_events_after last_ids.min || 0
|
14
|
+
listen_for_events
|
15
|
+
request_missing_events
|
25
16
|
event_channel.work_pool.join
|
26
17
|
end
|
27
18
|
|
28
|
-
def
|
29
|
-
|
19
|
+
def listen_for_events
|
20
|
+
subscribe_to event_queue do |delivery_info, properties, body|
|
21
|
+
event_received properties, body
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def request_missing_events
|
26
|
+
listen_for_replayed_events
|
27
|
+
send_request_for min_last_id
|
28
|
+
end
|
29
|
+
|
30
|
+
def listen_for_replayed_events
|
31
|
+
subscribe_to replay_queue do |delivery_info, properties, body|
|
32
|
+
event_received properties, body unless replay_done? body
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def send_request_for(id)
|
37
|
+
resend_request_exchange.publish id.to_s, routing_key: 'resend_request'
|
38
|
+
end
|
39
|
+
|
40
|
+
def replay_done?(body)
|
41
|
+
if 'replay_done' == body
|
42
|
+
puts 'Projections should be up to date now'
|
43
|
+
replay_queue.unbind(resend_exchange)
|
44
|
+
return true
|
45
|
+
end
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
def event_received(properties, body)
|
50
|
+
RELOADER.execute_if_updated
|
51
|
+
puts "Received #{properties.type} with #{body}"
|
52
|
+
ProjectionTypeRegistry.process properties.headers.deep_symbolize_keys, build_event(properties.type, JSON.parse(body))
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_event(type, data)
|
56
|
+
Object.const_get(type).new(data.deep_symbolize_keys)
|
57
|
+
end
|
58
|
+
|
59
|
+
def replay_queue
|
60
|
+
@replay_queue ||= event_channel.queue('', auto_delete: true).bind(resend_exchange)
|
61
|
+
end
|
62
|
+
|
63
|
+
def event_queue
|
64
|
+
@event_queue ||= event_channel.queue('', auto_delete: true).bind(event_exchange)
|
65
|
+
end
|
66
|
+
|
67
|
+
def min_last_id
|
68
|
+
ProjectionRepository.last_ids.min || 0
|
69
|
+
end
|
70
|
+
|
71
|
+
def subscribe_to(queue, &block)
|
72
|
+
queue.subscribe(&block)
|
30
73
|
end
|
31
74
|
|
32
75
|
def event_connection
|
@@ -42,14 +85,17 @@ module ActiveProjection
|
|
42
85
|
end
|
43
86
|
|
44
87
|
def resend_exchange
|
45
|
-
@resend_exchange ||= event_channel.
|
88
|
+
@resend_exchange ||= event_channel.fanout "resend_#{options[:event_exchange]}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def resend_request_exchange
|
92
|
+
@resend_request_exchange ||= event_channel.direct "resend_request_#{options[:event_exchange]}"
|
46
93
|
end
|
47
94
|
|
48
95
|
def options
|
49
96
|
@options
|
50
97
|
end
|
51
98
|
|
52
|
-
private
|
53
99
|
attr_writer :options
|
54
100
|
end
|
55
101
|
end
|
@@ -20,7 +20,7 @@ module ActiveProjection
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def evaluate(headers)
|
23
|
-
return false unless ProjectionRepository.solid? projection_id #
|
23
|
+
return false unless ProjectionRepository.solid? projection_id || headers[:replayed]# process only replayed events if projection is broken
|
24
24
|
last_id = ProjectionRepository.get_last_id projection_id
|
25
25
|
case
|
26
26
|
when last_id + 1 == headers[:store_id] #process incoming event
|
@@ -4,7 +4,7 @@ require_relative '../support/active_record'
|
|
4
4
|
describe ActiveProjection::ProjectionRepository do
|
5
5
|
before :all do
|
6
6
|
5.times do |i|
|
7
|
-
FactoryGirl.create :projection, id: i, class_name: "TestProjection#{i}"
|
7
|
+
FactoryGirl.create :projection, id: i, class_name: "TestProjection#{i}", last_id: 5 - i
|
8
8
|
end
|
9
9
|
end
|
10
10
|
describe 'create_or_get' do
|
@@ -24,4 +24,7 @@ describe ActiveProjection::ProjectionRepository do
|
|
24
24
|
expect(ActiveProjection::Projection.where(id:0).first.solid).to be_false
|
25
25
|
end
|
26
26
|
end
|
27
|
+
it 'returns array of last ids' do
|
28
|
+
expect(ActiveProjection::ProjectionRepository.last_ids).to eq [5,4,3,2,1]
|
29
|
+
end
|
27
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_projection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andreas Reischuck
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_event
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.2.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.2.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|