wonkavision 0.5.4 → 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +28 -16
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -21
- data/Rakefile +47 -47
- data/lib/wonkavision.rb +75 -74
- data/lib/wonkavision/acts_as_oompa_loompa.rb +22 -22
- data/lib/wonkavision/event_binding.rb +21 -21
- data/lib/wonkavision/event_context.rb +9 -9
- data/lib/wonkavision/event_coordinator.rb +75 -75
- data/lib/wonkavision/event_handler.rb +15 -15
- data/lib/wonkavision/event_namespace.rb +79 -79
- data/lib/wonkavision/event_path_segment.rb +35 -35
- data/lib/wonkavision/message_mapper.rb +30 -30
- data/lib/wonkavision/message_mapper/indifferent_access.rb +30 -26
- data/lib/wonkavision/message_mapper/map.rb +241 -153
- data/lib/wonkavision/persistence/mongo_mapper_adapter.rb +32 -32
- data/lib/wonkavision/persistence/mongoid_adapter.rb +32 -0
- data/lib/wonkavision/plugins.rb +30 -30
- data/lib/wonkavision/plugins/business_activity.rb +92 -92
- data/lib/wonkavision/plugins/business_activity/event_binding.rb +15 -15
- data/lib/wonkavision/plugins/callbacks.rb +182 -182
- data/lib/wonkavision/plugins/event_handling.rb +111 -111
- data/lib/wonkavision/plugins/timeline.rb +79 -79
- data/lib/wonkavision/version.rb +3 -3
- data/test/business_activity_test.rb +31 -31
- data/test/event_handler_test.rb +68 -69
- data/test/event_namespace_test.rb +108 -108
- data/test/event_path_segment_test.rb +41 -41
- data/test/log/test.log +817 -18354
- data/test/map_test.rb +315 -201
- data/test/message_mapper_test.rb +20 -20
- data/test/test_activity_models.rb +72 -72
- data/test/test_helper.rb +70 -63
- data/test/timeline_test.rb +55 -61
- data/test/wonkavision_test.rb +9 -9
- metadata +72 -12
- data/wonkavision.gemspec +0 -97
@@ -1,111 +1,111 @@
|
|
1
|
-
module Wonkavision
|
2
|
-
module Plugins
|
3
|
-
module EventHandling
|
4
|
-
|
5
|
-
def self.configure(handler,options)
|
6
|
-
handler.write_inheritable_attribute :event_handler_options, {}
|
7
|
-
handler.class_inheritable_reader :event_handler_options
|
8
|
-
|
9
|
-
handler.write_inheritable_attribute :bindings, []
|
10
|
-
handler.class_inheritable_reader :bindings
|
11
|
-
|
12
|
-
handler.write_inheritable_attribute :maps, []
|
13
|
-
handler.class_inheritable_reader :maps
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
module ClassMethods
|
18
|
-
def options
|
19
|
-
event_handler_options
|
20
|
-
end
|
21
|
-
|
22
|
-
def event_path(event_name)
|
23
|
-
return event_name.to_s if Wonkavision.is_absolute_path(event_name) #don't mess with an absolute path
|
24
|
-
Wonkavision.join(event_namespace,event_name)
|
25
|
-
end
|
26
|
-
|
27
|
-
def event_namespace(namespace=nil)
|
28
|
-
return event_handler_options[:event_namespace] unless namespace
|
29
|
-
event_handler_options[:event_namespace] = namespace
|
30
|
-
end
|
31
|
-
alias :namespace :event_namespace
|
32
|
-
|
33
|
-
def map(condition = nil,&block)
|
34
|
-
maps << [condition,block]
|
35
|
-
end
|
36
|
-
|
37
|
-
def handle(name,*args,&block)
|
38
|
-
binding = create_binding(name,self,*args)
|
39
|
-
binding.subscribe_to_events do |event_data,event_path|
|
40
|
-
ctx = Wonkavision::EventContext.new(event_data,event_path,binding,block)
|
41
|
-
handler = instantiate_handler(ctx)
|
42
|
-
handler.instance_variable_set(:@wonkavision_event_context, ctx)
|
43
|
-
handler.handle_event
|
44
|
-
end
|
45
|
-
bindings << binding
|
46
|
-
binding
|
47
|
-
end
|
48
|
-
|
49
|
-
def instantiate_handler(event_context)
|
50
|
-
self.new
|
51
|
-
end
|
52
|
-
|
53
|
-
def create_binding(name,handler,*args)
|
54
|
-
Wonkavision::EventBinding.new(name,handler,*args)
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
module InstanceMethods
|
60
|
-
|
61
|
-
def handled?
|
62
|
-
@wonkavision_event_handled ||= false
|
63
|
-
end
|
64
|
-
|
65
|
-
def handled=(handled)
|
66
|
-
@wonkavision_event_handled = handled
|
67
|
-
end
|
68
|
-
|
69
|
-
def event_context
|
70
|
-
@wonkavision_event_context
|
71
|
-
end
|
72
|
-
|
73
|
-
def handle_event
|
74
|
-
ctx = @wonkavision_event_context
|
75
|
-
ctx.data = map(ctx.data,ctx.path)
|
76
|
-
handler = ctx.callback
|
77
|
-
|
78
|
-
if handler && handler.respond_to?(:call) && handler.respond_to?(:arity)
|
79
|
-
case handler.arity
|
80
|
-
when 3 then handler.call(ctx.data,ctx.path,self)
|
81
|
-
when 2 then handler.call(ctx.data,ctx.path)
|
82
|
-
when 1 then handler.call
|
83
|
-
else instance_eval &handler
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
protected
|
89
|
-
def map(data,path)
|
90
|
-
self.class.maps.each do |map_def|
|
91
|
-
condition = map_def[0]
|
92
|
-
map_block = map_def[1]
|
93
|
-
return Wonkavision::MessageMapper.execute(map_block,data) if map?(condition,data,path)
|
94
|
-
end
|
95
|
-
data.is_a?(Hash) ? data.dup : data
|
96
|
-
end
|
97
|
-
|
98
|
-
def map?(condition,data,path)
|
99
|
-
return true unless condition && condition.to_s != 'all' && condition.to_s != '*'
|
100
|
-
return path =~ condition if condition.is_a?(Regexp)
|
101
|
-
if (condition.is_a?(Proc))
|
102
|
-
return condition.call if condition.arity <= 0
|
103
|
-
return condition.call(path) if condition.arity == 1
|
104
|
-
return condition.call(path,data)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
1
|
+
module Wonkavision
|
2
|
+
module Plugins
|
3
|
+
module EventHandling
|
4
|
+
|
5
|
+
def self.configure(handler,options)
|
6
|
+
handler.write_inheritable_attribute :event_handler_options, {}
|
7
|
+
handler.class_inheritable_reader :event_handler_options
|
8
|
+
|
9
|
+
handler.write_inheritable_attribute :bindings, []
|
10
|
+
handler.class_inheritable_reader :bindings
|
11
|
+
|
12
|
+
handler.write_inheritable_attribute :maps, []
|
13
|
+
handler.class_inheritable_reader :maps
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def options
|
19
|
+
event_handler_options
|
20
|
+
end
|
21
|
+
|
22
|
+
def event_path(event_name)
|
23
|
+
return event_name.to_s if Wonkavision.is_absolute_path(event_name) #don't mess with an absolute path
|
24
|
+
Wonkavision.join(event_namespace,event_name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def event_namespace(namespace=nil)
|
28
|
+
return event_handler_options[:event_namespace] unless namespace
|
29
|
+
event_handler_options[:event_namespace] = namespace
|
30
|
+
end
|
31
|
+
alias :namespace :event_namespace
|
32
|
+
|
33
|
+
def map(condition = nil,&block)
|
34
|
+
maps << [condition,block]
|
35
|
+
end
|
36
|
+
|
37
|
+
def handle(name,*args,&block)
|
38
|
+
binding = create_binding(name,self,*args)
|
39
|
+
binding.subscribe_to_events do |event_data,event_path|
|
40
|
+
ctx = Wonkavision::EventContext.new(event_data,event_path,binding,block)
|
41
|
+
handler = instantiate_handler(ctx)
|
42
|
+
handler.instance_variable_set(:@wonkavision_event_context, ctx)
|
43
|
+
handler.handle_event
|
44
|
+
end
|
45
|
+
bindings << binding
|
46
|
+
binding
|
47
|
+
end
|
48
|
+
|
49
|
+
def instantiate_handler(event_context)
|
50
|
+
self.new
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_binding(name,handler,*args)
|
54
|
+
Wonkavision::EventBinding.new(name,handler,*args)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
module InstanceMethods
|
60
|
+
|
61
|
+
def handled?
|
62
|
+
@wonkavision_event_handled ||= false
|
63
|
+
end
|
64
|
+
|
65
|
+
def handled=(handled)
|
66
|
+
@wonkavision_event_handled = handled
|
67
|
+
end
|
68
|
+
|
69
|
+
def event_context
|
70
|
+
@wonkavision_event_context
|
71
|
+
end
|
72
|
+
|
73
|
+
def handle_event
|
74
|
+
ctx = @wonkavision_event_context
|
75
|
+
ctx.data = map(ctx.data,ctx.path)
|
76
|
+
handler = ctx.callback
|
77
|
+
|
78
|
+
if handler && handler.respond_to?(:call) && handler.respond_to?(:arity)
|
79
|
+
case handler.arity
|
80
|
+
when 3 then handler.call(ctx.data,ctx.path,self)
|
81
|
+
when 2 then handler.call(ctx.data,ctx.path)
|
82
|
+
when 1 then handler.call(ctx.data)
|
83
|
+
else instance_eval &handler
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
def map(data,path)
|
90
|
+
self.class.maps.each do |map_def|
|
91
|
+
condition = map_def[0]
|
92
|
+
map_block = map_def[1]
|
93
|
+
return Wonkavision::MessageMapper.execute(map_block,data) if map?(condition,data,path)
|
94
|
+
end
|
95
|
+
data.is_a?(Hash) ? data.dup : data
|
96
|
+
end
|
97
|
+
|
98
|
+
def map?(condition,data,path)
|
99
|
+
return true unless condition && condition.to_s != 'all' && condition.to_s != '*'
|
100
|
+
return path =~ condition if condition.is_a?(Regexp)
|
101
|
+
if (condition.is_a?(Proc))
|
102
|
+
return condition.call if condition.arity <= 0
|
103
|
+
return condition.call(path) if condition.arity == 1
|
104
|
+
return condition.call(path,data)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -1,80 +1,80 @@
|
|
1
|
-
module Wonkavision
|
2
|
-
module Plugins
|
3
|
-
module Timeline
|
4
|
-
def self.all
|
5
|
-
@@all ||= []
|
6
|
-
end
|
7
|
-
|
8
|
-
def self.configure(activity,options={})
|
9
|
-
activity.ensure_wonkavision_plugin(Wonkavision::Plugins::BusinessActivity,options)
|
10
|
-
activity.write_inheritable_attribute :timeline_milestones, []
|
11
|
-
activity.class_inheritable_reader :timeline_milestones
|
12
|
-
|
13
|
-
options = {
|
14
|
-
:timeline_field => "timeline",
|
15
|
-
:latest_milestone_field => "latest_milestone",
|
16
|
-
:event_time_key => "event_time"
|
17
|
-
}.merge(options)
|
18
|
-
|
19
|
-
activity.business_activity_options.merge!(options)
|
20
|
-
|
21
|
-
activity.define_document_key(activity.timeline_field,Hash,:default=>{})
|
22
|
-
activity.define_document_key(activity.latest_milestone_field, String, :default=>"awaiting_first_event")
|
23
|
-
|
24
|
-
Timeline.all << activity
|
25
|
-
end
|
26
|
-
|
27
|
-
module ClassMethods
|
28
|
-
|
29
|
-
def milestone(name,*args)
|
30
|
-
timeline_milestones << event(name,*args) do
|
31
|
-
ctx = @wonkavision_event_context
|
32
|
-
event_time = self.class.extract_event_time(ctx.data,ctx.path)
|
33
|
-
prev_event_time = self[timeline_field][name]
|
34
|
-
unless prev_event_time
|
35
|
-
self[timeline_field][name] = event_time
|
36
|
-
#If the event being processed happened earlier than a previously
|
37
|
-
#recorded event, we don't want to overwrite state of the activity, as
|
38
|
-
#it is already more up to date than the incoming event.
|
39
|
-
latest_ms = self[latest_milestone_field]
|
40
|
-
unless latest_ms &&
|
41
|
-
(last_event = self[timeline_field][latest_ms]) &&
|
42
|
-
last_event > event_time
|
43
|
-
self.class.update_activity(self,ctx.data)
|
44
|
-
self[latest_milestone_field] = name
|
45
|
-
end
|
46
|
-
:updated
|
47
|
-
else
|
48
|
-
:handled #If there was a previous event time for this milestone, we will just skip this event
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def convert_time(time)
|
54
|
-
if (time.is_a?(Hash)) && (time.keys.include?(:date) || time.keys.include?(:time))
|
55
|
-
time = "#{time[:date]} #{time[:time]}".strip
|
56
|
-
end
|
57
|
-
time ? time.to_time : nil
|
58
|
-
end
|
59
|
-
|
60
|
-
def extract_event_time(event_data,event_path)
|
61
|
-
convert_time(event_data.delete(event_time_key.to_s)) || Time.now.utc
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
module Fields
|
66
|
-
def timeline_field
|
67
|
-
business_activity_options[:timeline_field]
|
68
|
-
end
|
69
|
-
|
70
|
-
def latest_milestone_field
|
71
|
-
business_activity_options[:latest_milestone_field]
|
72
|
-
end
|
73
|
-
|
74
|
-
def event_time_key
|
75
|
-
business_activity_options[:event_time_key]
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
1
|
+
module Wonkavision
|
2
|
+
module Plugins
|
3
|
+
module Timeline
|
4
|
+
def self.all
|
5
|
+
@@all ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configure(activity,options={})
|
9
|
+
activity.ensure_wonkavision_plugin(Wonkavision::Plugins::BusinessActivity,options)
|
10
|
+
activity.write_inheritable_attribute :timeline_milestones, []
|
11
|
+
activity.class_inheritable_reader :timeline_milestones
|
12
|
+
|
13
|
+
options = {
|
14
|
+
:timeline_field => "timeline",
|
15
|
+
:latest_milestone_field => "latest_milestone",
|
16
|
+
:event_time_key => "event_time"
|
17
|
+
}.merge(options)
|
18
|
+
|
19
|
+
activity.business_activity_options.merge!(options)
|
20
|
+
|
21
|
+
activity.define_document_key(activity.timeline_field,Hash,:default=>{})
|
22
|
+
activity.define_document_key(activity.latest_milestone_field, String, :default=>"awaiting_first_event")
|
23
|
+
|
24
|
+
Timeline.all << activity
|
25
|
+
end
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
|
29
|
+
def milestone(name,*args)
|
30
|
+
timeline_milestones << event(name,*args) do
|
31
|
+
ctx = @wonkavision_event_context
|
32
|
+
event_time = self.class.extract_event_time(ctx.data,ctx.path)
|
33
|
+
prev_event_time = self[timeline_field][name]
|
34
|
+
unless prev_event_time
|
35
|
+
self[timeline_field][name] = event_time
|
36
|
+
#If the event being processed happened earlier than a previously
|
37
|
+
#recorded event, we don't want to overwrite state of the activity, as
|
38
|
+
#it is already more up to date than the incoming event.
|
39
|
+
latest_ms = self[latest_milestone_field]
|
40
|
+
unless latest_ms &&
|
41
|
+
(last_event = self[timeline_field][latest_ms]) &&
|
42
|
+
last_event > event_time
|
43
|
+
self.class.update_activity(self,ctx.data)
|
44
|
+
self[latest_milestone_field] = name
|
45
|
+
end
|
46
|
+
:updated
|
47
|
+
else
|
48
|
+
:handled #If there was a previous event time for this milestone, we will just skip this event
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def convert_time(time)
|
54
|
+
if (time.is_a?(Hash)) && (time.keys.include?(:date) || time.keys.include?(:time))
|
55
|
+
time = "#{time[:date]} #{time[:time]}".strip
|
56
|
+
end
|
57
|
+
time ? time.to_time : nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def extract_event_time(event_data,event_path)
|
61
|
+
convert_time(event_data.delete(event_time_key.to_s)) || Time.now.utc
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module Fields
|
66
|
+
def timeline_field
|
67
|
+
business_activity_options[:timeline_field]
|
68
|
+
end
|
69
|
+
|
70
|
+
def latest_milestone_field
|
71
|
+
business_activity_options[:latest_milestone_field]
|
72
|
+
end
|
73
|
+
|
74
|
+
def event_time_key
|
75
|
+
business_activity_options[:event_time_key]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
80
|
end
|
data/lib/wonkavision/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Wonkavision
|
2
|
-
VERSION = '0.5.
|
3
|
-
end
|
1
|
+
module Wonkavision
|
2
|
+
VERSION = '0.5.9'
|
3
|
+
end
|
@@ -1,31 +1,31 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "test_activity_models"
|
3
|
-
|
4
|
-
class BusinessActivityTest < ActiveSupport::TestCase
|
5
|
-
context "TestBusinessActivity" do
|
6
|
-
should "configure namespace from DSL" do
|
7
|
-
assert_equal :test, TestBusinessActivity.event_namespace
|
8
|
-
end
|
9
|
-
should "configure correlation identifiers from DSL" do
|
10
|
-
assert_equal({:event=>:test_id, :model=>:test_id}, TestBusinessActivity.correlate_by)
|
11
|
-
end
|
12
|
-
should "register activity with global registry" do
|
13
|
-
assert_equal 1, Wonkavision::Plugins::BusinessActivity.all.length
|
14
|
-
assert_equal TestBusinessActivity, Wonkavision::Plugins::BusinessActivity.all[0]
|
15
|
-
end
|
16
|
-
|
17
|
-
should "register correlation ids with each activity" do
|
18
|
-
ids = Wonkavision::Plugins::BusinessActivity.all[0].correlation_ids
|
19
|
-
assert_equal 1, ids.length
|
20
|
-
assert_equal :test_id, ids[0][:event]
|
21
|
-
end
|
22
|
-
|
23
|
-
should "use per binding correlation ids when specified" do
|
24
|
-
event = {"alt_event_id"=>"123","another_field"=>"hi there"}
|
25
|
-
Wonkavision.event_coordinator.receive_event("test/evt5",event)
|
26
|
-
assert activity = TestBusinessActivity.
|
27
|
-
assert_equal "hi there", activity.another_field
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
1
|
+
require "test_helper"
|
2
|
+
require "test_activity_models"
|
3
|
+
|
4
|
+
class BusinessActivityTest < ActiveSupport::TestCase
|
5
|
+
context "TestBusinessActivity" do
|
6
|
+
should "configure namespace from DSL" do
|
7
|
+
assert_equal :test, TestBusinessActivity.event_namespace
|
8
|
+
end
|
9
|
+
should "configure correlation identifiers from DSL" do
|
10
|
+
assert_equal({:event=>:test_id, :model=>:test_id}, TestBusinessActivity.correlate_by)
|
11
|
+
end
|
12
|
+
should "register activity with global registry" do
|
13
|
+
assert_equal 1, Wonkavision::Plugins::BusinessActivity.all.length
|
14
|
+
assert_equal TestBusinessActivity, Wonkavision::Plugins::BusinessActivity.all[0]
|
15
|
+
end
|
16
|
+
|
17
|
+
should "register correlation ids with each activity" do
|
18
|
+
ids = Wonkavision::Plugins::BusinessActivity.all[0].correlation_ids
|
19
|
+
assert_equal 1, ids.length
|
20
|
+
assert_equal :test_id, ids[0][:event]
|
21
|
+
end
|
22
|
+
|
23
|
+
should "use per binding correlation ids when specified" do
|
24
|
+
event = {"alt_event_id"=>"123","another_field"=>"hi there"}
|
25
|
+
Wonkavision.event_coordinator.receive_event("test/evt5",event)
|
26
|
+
assert activity = TestBusinessActivity.first(:conditions=>{:alt_model_id=>"123"})
|
27
|
+
assert_equal "hi there", activity.another_field
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|