wonkavision 0.5.0 → 0.5.1

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.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,5 @@
1
+ == 0.5.1
2
+ * Ensure that subscriptions to an event namespace will only get notified once per incoming message
1
3
 
2
4
  == 0.5.0
3
5
  * Initial release
@@ -1,33 +1,33 @@
1
- module Wonkavision
2
-
3
- class Event < Wonkavision::EventPathSegment
4
-
5
- def initialize(name, namespace, opts={})
6
- super name,namespace,opts
7
- @source_events = []
8
- source_events(*opts.delete(:source_events)) if opts.keys.include?(:source_events)
9
- end
10
-
11
- def matches(event_path)
12
- event_path == path || @source_events.detect{|evt|evt.matches(event_path)} != nil
13
- end
14
-
15
- def notify_subscribers(event_data,event_path)
16
- super(event_data,self.path)
17
- end
18
-
19
- def source_events(*args)
20
- return @source_events if args.blank?
21
- @source_events = @source_events.concat(args.map do |source|
22
- source_ns = namespace
23
- if (source=~/^\/.*/)
24
- source_ns = root_namespace
25
- source = source[1..-1]
26
- end
27
- source_ns.find_or_create(source)
28
- end)
29
- end
30
- end
31
-
32
- end
1
+ module Wonkavision
2
+
3
+ class Event < Wonkavision::EventPathSegment
4
+
5
+ def initialize(name, namespace, opts={})
6
+ super name,namespace,opts
7
+ @source_events = []
8
+ source_events(*opts.delete(:source_events)) if opts.keys.include?(:source_events)
9
+ end
10
+
11
+ def matches(event_path)
12
+ event_path == path || @source_events.detect{|evt|evt.matches(event_path)} != nil
13
+ end
14
+
15
+ def notify_subscribers(event_data,event_path)
16
+ super(event_data,self.path)
17
+ end
18
+
19
+ def source_events(*args)
20
+ return @source_events if args.blank?
21
+ @source_events = @source_events.concat(args.map do |source|
22
+ source_ns = namespace
23
+ if (source=~/^\/.*/)
24
+ source_ns = root_namespace
25
+ source = source[1..-1]
26
+ end
27
+ source_ns.find_or_create(source)
28
+ end)
29
+ end
30
+ end
31
+
32
+ end
33
33
 
@@ -39,7 +39,7 @@ module Wonkavision
39
39
  return unless event_data = process_incoming_event(event_path,event_data)
40
40
 
41
41
  event_path = Wonkavision.normalize_event_path(event_path)
42
- targets = root_namespace.find_matching_events(event_path)
42
+ targets = root_namespace.find_matching_segments(event_path).values
43
43
  #If the event wasn't matched, maybe someone is subscribing to '/*' ?
44
44
  targets = [root_namespace] if targets.blank?
45
45
  targets.each{|target|target.notify_subscribers(event_data,event_path)}
@@ -28,13 +28,13 @@ module Wonkavision
28
28
  end
29
29
  end
30
30
 
31
- def find_matching_events (event_path)
32
- events = []
31
+ def find_matching_segments (event_path)
32
+ selected = {}
33
33
  @children.each_value do |child|
34
34
  if (child.is_a?(Wonkavision::Event))
35
- events << child if child.matches(event_path)
35
+ select_segment(child,selected) if child.matches(event_path)
36
36
  elsif (child.is_a?(Wonkavision::EventNamespace))
37
- events.concat(child.find_matching_events(event_path))
37
+ selected.merge!(child.find_matching_segments(event_path))
38
38
  else
39
39
  raise "An unexpected child type was encountered in find_matching_events #{child.class}"
40
40
  end
@@ -42,8 +42,8 @@ module Wonkavision
42
42
  #If no child was found, and the event matches this namespace, we should add ourselves to the list.
43
43
  #This is not necessary if any child event was located, because in that case event notifications
44
44
  #would bubble up to us anyway. If no event was found, there's nobody to blow the bubble but us.
45
- events << self if events.blank? && matches_event(event_path)
46
- events
45
+ select_segment(self,selected) if selected.blank? && matches_event(event_path)
46
+ selected
47
47
  end
48
48
 
49
49
  def matches_event(event_path)
@@ -54,7 +54,7 @@ module Wonkavision
54
54
  def namespace(*args)
55
55
  return super if args.blank?
56
56
  name, opts = args.shift, (args.shift || {})
57
- ns = Wonkavision::EventNamespace.new(name,self,opts)
57
+ ns = @children[name] || Wonkavision::EventNamespace.new(name,self,opts)
58
58
  yield ns if block_given?
59
59
  @children[ns.name] = ns
60
60
  ns
@@ -63,10 +63,17 @@ module Wonkavision
63
63
  def event(*args)
64
64
  name, opts = args.shift, args.extract_options!
65
65
  opts[:source_events] = (opts[:source_events] || []).concat(args) unless args.blank?
66
- evt = Wonkavision::Event.new(name,self,opts)
66
+ evt = @children[name] || Wonkavision::Event.new(name,self,opts)
67
67
  yield evt if block_given?
68
68
  @children[evt.name] = evt
69
69
  evt
70
70
  end
71
+
72
+ private
73
+ def select_segment(segment,selected)
74
+ selected[segment.name] = segment
75
+ select_segment(segment.namespace,selected) if segment.namespace
76
+ end
77
+
71
78
  end
72
79
  end
@@ -22,7 +22,6 @@ module Wonkavision
22
22
  @subscribers.each do |sub|
23
23
  sub.call(event_data,event_path)
24
24
  end
25
- namespace.notify_subscribers(event_data,event_path) if namespace
26
25
  end
27
26
 
28
27
  def root_namespace
@@ -1,3 +1,3 @@
1
1
  module Wonkavision
2
- VERSION = '0.5.0'
2
+ VERSION = '0.5.1'
3
3
  end
@@ -23,8 +23,8 @@ class EventHandlerTest < ActiveSupport::TestCase
23
23
  should "handle subscriptions to the configured namespace" do
24
24
  TestEventHandler.reset
25
25
  Wonkavision.event_coordinator.receive_event("vermicious/hose",1)
26
- Wonkavision.event_coordinator.receive_event("vermicious/kid",2)
27
- Wonkavision.event_coordinator.receive_event("vermiciouser/kid",3)
26
+ Wonkavision.event_coordinator.receive_event("vermicious/dog",2)
27
+ Wonkavision.event_coordinator.receive_event("vermiciouser/knid",3)
28
28
  puts TestEventHandler.knids.inspect
29
29
  assert_equal 2, TestEventHandler.knids.length
30
30
  assert_equal 1, TestEventHandler.knids[0][0]
@@ -42,6 +42,19 @@ class EventHandlerTest < ActiveSupport::TestCase
42
42
  assert_equal 3, TestEventHandler.knids[2][0]
43
43
 
44
44
  end
45
+
46
+ should "only notify once per namespace, even if multiple events are matched in a given namespace" do
47
+ TestEventHandler.reset
48
+
49
+ Wonkavision.event_coordinator.map do |events|
50
+ events.namespace :vermicious do |v|
51
+ v.event :composite, 'oompa','loompa'
52
+ end
53
+ end
54
+
55
+ Wonkavision.event_coordinator.receive_event("vermicious/oompa",1);
56
+ assert_equal 1, TestEventHandler.knids.length
57
+ end
45
58
  end
46
59
 
47
60
  end
@@ -1,109 +1,109 @@
1
- require "test_helper"
2
-
3
- class EventNamespaceTest < ActiveSupport::TestCase
4
-
5
- context "EventNamespace#namespace" do
6
- should "return the namespace if no arguments are provided" do
7
- ns1 = Wonkavision::EventNamespace.new :ns1
8
- ns2 = Wonkavision::EventNamespace.new :ns2, ns1
9
- assert_equal ns1, ns2.namespace
10
- end
11
- should "create a new namespace with the provided name" do
12
- ns1 = Wonkavision::EventNamespace.new :ns1
13
- ns2 = ns1.namespace :ns2
14
- assert_equal ns1, ns2.namespace
15
- assert_equal ns2, ns1.children[ns2.name]
16
- end
17
- should "yield the new namespace for modification" do
18
- ns1 = Wonkavision::EventNamespace.new :ns1
19
- ns2 = ns1.namespace(:ns2){|child|child.namespace(:ns3)}
20
- assert_equal 1, ns2.children.length
21
- assert_equal "ns3", ns2.children.keys[0]
22
- end
23
- end
24
-
25
- context "EventNamespace#event" do
26
- should "create a new event with the provided name" do
27
- ns1 = Wonkavision::EventNamespace.new :ns1
28
- evt = ns1.event :evt1
29
- assert_equal ns1, evt.namespace
30
- assert_equal evt, ns1.children[evt.name]
31
- end
32
- should "provide source_events to the new event if in the opts hash" do
33
- ns1 = Wonkavision::EventNamespace.new :ns1
34
- evt = ns1.event :evt1, :source_events=>"evt2"
35
- assert_equal "evt2", evt.source_events[0].name
36
- end
37
- should "yield new event to block if provided" do
38
- ns1 = Wonkavision::EventNamespace.new :ns1
39
- evt = ns1.event(:evt1) {|evt|evt.source_events "evt2"}
40
- assert_equal "evt2", evt.source_events[0].name
41
- end
42
- end
43
-
44
- context "EventNamespace#find_or_create" do
45
- should "find an existing direct child event" do
46
- ns1 = Wonkavision::EventNamespace.new :ns1
47
- evt = ns1.event :evt1
48
- assert_equal evt, ns1.find_or_create("evt1")
49
- end
50
- should "find a nested event" do
51
- ns1 = Wonkavision::EventNamespace.new :ns1
52
- evt = ns1.namespace(:ns2).event(:evt1)
53
- assert_equal evt, ns1.find_or_create("ns2/evt1")
54
- end
55
- should "find a direct child namespace" do
56
- ns1 = Wonkavision::EventNamespace.new :ns1
57
- ns2 = ns1.namespace :ns2
58
- assert_equal ns2, ns1.find_or_create("ns2")
59
- end
60
- should "find a nested namespace" do
61
- ns1 = Wonkavision::EventNamespace.new :ns1
62
- ns3 = ns1.namespace(:ns2).namespace(:ns3)
63
- assert_equal ns3, ns1.find_or_create("ns2/ns3")
64
- end
65
- should "create a top level child event if not found" do
66
- ns1 = Wonkavision::EventNamespace.new :ns1
67
- evt = ns1.find_or_create("TheNewEvent")
68
- assert_equal "ns1/the_new_event", evt.path
69
- end
70
- should "create a top level child namespace if not found" do
71
- ns1 = Wonkavision::EventNamespace.new :ns1
72
- ns2 = ns1.find_or_create("TheNewNamespace",:namespace)
73
- assert_equal "ns1/the_new_namespace",ns2.path
74
- end
75
- should "create a nested event if namespace exits but event not found" do
76
- ns1 = Wonkavision::EventNamespace.new(:ns1)
77
- ns1.namespace :ns2
78
- evt = ns1.find_or_create("ns2/new_event")
79
- assert_equal "ns1/ns2/new_event",evt.path
80
- end
81
- should "create a nested namespace and event if not found" do
82
- ns1 = Wonkavision::EventNamespace.new :ns1
83
- evt = ns1.find_or_create("ns3/new_event")
84
- assert_equal "ns1/ns3/new_event",evt.path
85
- assert ns1.children["ns3"].children["new_event"]
86
- end
87
- should "create nested namespaces if not found" do
88
- ns1 = Wonkavision::EventNamespace.new :ns1
89
- ns3 = ns1.find_or_create "not/found/my/friend",:namespace
90
- assert ns3.is_a?(Wonkavision::EventNamespace)
91
- assert_equal "ns1/not/found/my/friend", ns3.path
92
- end
93
- end
94
- context "EventNamespace#find_matching_values" do
95
- should "find all events matching the specified path" do
96
- ns1 = Wonkavision::EventNamespace.new :ns1
97
- ns2 = ns1.namespace :ns2
98
- ns2.event "my_event"
99
- ns2.event :e1, "my_event"
100
- ns3 = ns2.namespace :ns3
101
- ns3.event :e2, "/ns2/my_event"
102
- ns4 = ns1.namespace :ns4
103
- ns4.event :e3, "/ns2/my_event"
104
- ns4.event "my_event"
105
-
106
- assert_equal 4, ns1.find_matching_events("ns1/ns2/my_event").length
107
- end
108
- end
1
+ require "test_helper"
2
+
3
+ class EventNamespaceTest < ActiveSupport::TestCase
4
+
5
+ context "EventNamespace#namespace" do
6
+ should "return the namespace if no arguments are provided" do
7
+ ns1 = Wonkavision::EventNamespace.new :ns1
8
+ ns2 = Wonkavision::EventNamespace.new :ns2, ns1
9
+ assert_equal ns1, ns2.namespace
10
+ end
11
+ should "create a new namespace with the provided name" do
12
+ ns1 = Wonkavision::EventNamespace.new :ns1
13
+ ns2 = ns1.namespace :ns2
14
+ assert_equal ns1, ns2.namespace
15
+ assert_equal ns2, ns1.children[ns2.name]
16
+ end
17
+ should "yield the new namespace for modification" do
18
+ ns1 = Wonkavision::EventNamespace.new :ns1
19
+ ns2 = ns1.namespace(:ns2){|child|child.namespace(:ns3)}
20
+ assert_equal 1, ns2.children.length
21
+ assert_equal "ns3", ns2.children.keys[0]
22
+ end
23
+ end
24
+
25
+ context "EventNamespace#event" do
26
+ should "create a new event with the provided name" do
27
+ ns1 = Wonkavision::EventNamespace.new :ns1
28
+ evt = ns1.event :evt1
29
+ assert_equal ns1, evt.namespace
30
+ assert_equal evt, ns1.children[evt.name]
31
+ end
32
+ should "provide source_events to the new event if in the opts hash" do
33
+ ns1 = Wonkavision::EventNamespace.new :ns1
34
+ evt = ns1.event :evt1, :source_events=>"evt2"
35
+ assert_equal "evt2", evt.source_events[0].name
36
+ end
37
+ should "yield new event to block if provided" do
38
+ ns1 = Wonkavision::EventNamespace.new :ns1
39
+ evt = ns1.event(:evt1) {|evt|evt.source_events "evt2"}
40
+ assert_equal "evt2", evt.source_events[0].name
41
+ end
42
+ end
43
+
44
+ context "EventNamespace#find_or_create" do
45
+ should "find an existing direct child event" do
46
+ ns1 = Wonkavision::EventNamespace.new :ns1
47
+ evt = ns1.event :evt1
48
+ assert_equal evt, ns1.find_or_create("evt1")
49
+ end
50
+ should "find a nested event" do
51
+ ns1 = Wonkavision::EventNamespace.new :ns1
52
+ evt = ns1.namespace(:ns2).event(:evt1)
53
+ assert_equal evt, ns1.find_or_create("ns2/evt1")
54
+ end
55
+ should "find a direct child namespace" do
56
+ ns1 = Wonkavision::EventNamespace.new :ns1
57
+ ns2 = ns1.namespace :ns2
58
+ assert_equal ns2, ns1.find_or_create("ns2")
59
+ end
60
+ should "find a nested namespace" do
61
+ ns1 = Wonkavision::EventNamespace.new :ns1
62
+ ns3 = ns1.namespace(:ns2).namespace(:ns3)
63
+ assert_equal ns3, ns1.find_or_create("ns2/ns3")
64
+ end
65
+ should "create a top level child event if not found" do
66
+ ns1 = Wonkavision::EventNamespace.new :ns1
67
+ evt = ns1.find_or_create("TheNewEvent")
68
+ assert_equal "ns1/the_new_event", evt.path
69
+ end
70
+ should "create a top level child namespace if not found" do
71
+ ns1 = Wonkavision::EventNamespace.new :ns1
72
+ ns2 = ns1.find_or_create("TheNewNamespace",:namespace)
73
+ assert_equal "ns1/the_new_namespace",ns2.path
74
+ end
75
+ should "create a nested event if namespace exits but event not found" do
76
+ ns1 = Wonkavision::EventNamespace.new(:ns1)
77
+ ns1.namespace :ns2
78
+ evt = ns1.find_or_create("ns2/new_event")
79
+ assert_equal "ns1/ns2/new_event",evt.path
80
+ end
81
+ should "create a nested namespace and event if not found" do
82
+ ns1 = Wonkavision::EventNamespace.new :ns1
83
+ evt = ns1.find_or_create("ns3/new_event")
84
+ assert_equal "ns1/ns3/new_event",evt.path
85
+ assert ns1.children["ns3"].children["new_event"]
86
+ end
87
+ should "create nested namespaces if not found" do
88
+ ns1 = Wonkavision::EventNamespace.new :ns1
89
+ ns3 = ns1.find_or_create "not/found/my/friend",:namespace
90
+ assert ns3.is_a?(Wonkavision::EventNamespace)
91
+ assert_equal "ns1/not/found/my/friend", ns3.path
92
+ end
93
+ end
94
+ context "EventNamespace#find_matching_values" do
95
+ should "find all events matching the specified path" do
96
+ ns1 = Wonkavision::EventNamespace.new :ns1
97
+ ns2 = ns1.namespace :ns2
98
+ ns2.event "my_event"
99
+ ns2.event :e1, "my_event"
100
+ ns3 = ns2.namespace :ns3
101
+ ns3.event :e2, "/ns2/my_event"
102
+ ns4 = ns1.namespace :ns4
103
+ ns4.event :e3, "/ns2/my_event"
104
+ ns4.event "my_event"
105
+
106
+ assert_equal 8, ns1.find_matching_segments("ns1/ns2/my_event").length
107
+ end
108
+ end
109
109
  end
@@ -1,56 +1,42 @@
1
- require "test_helper"
2
-
3
- class EventPathSegmentTest < ActiveSupport::TestCase
4
- context "EventPathSegment#path" do
5
- should "not include path segments for root segments" do
6
- assert_equal "a_segment", Wonkavision::EventPathSegment.new(:a_segment).path
7
- end
8
- should "join the parent namespace in the path for non root segments" do
9
- ns1 = Wonkavision::EventPathSegment.new(:ns_1)
10
- ns2 = Wonkavision::EventPathSegment.new(:ns_2, ns1)
11
- assert_equal "ns_1/ns_2/a_segment", Wonkavision::EventPathSegment.new(:a_segment,ns2).path
12
- end
13
- should "ignore segments in a hierarchy with a nil name" do
14
- ns1 = Wonkavision::EventPathSegment.new(:ns_1)
15
- ns2 = Wonkavision::EventPathSegment.new(nil,ns1)
16
- assert_equal "ns_1/a_segment", Wonkavision::EventPathSegment.new(:a_segment,ns2).path
17
- end
18
- end
19
-
20
- context "EventPathSegment#subscribe" do
21
- should "Add the provided block to the list of subscribers" do
22
- seg = Wonkavision::EventPathSegment.new
23
- x = 1
24
- seg.subscribe {x+=1 }
25
- assert_equal 1, seg.subscribers.length
26
- seg.subscribers[0].call
27
- assert_equal 2, x
28
- end
29
- end
30
-
31
- context "EventPathSegment#notifiy_subscribers" do
32
- should "call each subscribed block" do
33
- seg = Wonkavision::EventPathSegment.new
34
- x = 1
35
- seg.subscribe {x+=1}
36
- seg.subscribe {|data,path|x+=data+path}
37
- seg.notify_subscribers(5,2)
38
-
39
- assert_equal 9, x
40
- end
41
- should "bubble the call to notify_subscribers up the hierarchy" do
42
- called = []
43
- ns1 = Wonkavision::EventPathSegment.new(:ns1)
44
- ns1.subscribe {called << ns1}
45
- ns2 = Wonkavision::EventPathSegment.new(:ns2,ns1)
46
- ns2.subscribe {called << ns2}
47
- evt = Wonkavision::EventPathSegment.new(:evt,ns2)
48
-
49
- evt.notify_subscribers(nil)
50
-
51
- assert_equal 2, called.length
52
- assert_equal ns2, called[0]
53
- assert_equal ns1, called[1]
54
- end
55
- end
1
+ require "test_helper"
2
+
3
+ class EventPathSegmentTest < ActiveSupport::TestCase
4
+ context "EventPathSegment#path" do
5
+ should "not include path segments for root segments" do
6
+ assert_equal "a_segment", Wonkavision::EventPathSegment.new(:a_segment).path
7
+ end
8
+ should "join the parent namespace in the path for non root segments" do
9
+ ns1 = Wonkavision::EventPathSegment.new(:ns_1)
10
+ ns2 = Wonkavision::EventPathSegment.new(:ns_2, ns1)
11
+ assert_equal "ns_1/ns_2/a_segment", Wonkavision::EventPathSegment.new(:a_segment,ns2).path
12
+ end
13
+ should "ignore segments in a hierarchy with a nil name" do
14
+ ns1 = Wonkavision::EventPathSegment.new(:ns_1)
15
+ ns2 = Wonkavision::EventPathSegment.new(nil,ns1)
16
+ assert_equal "ns_1/a_segment", Wonkavision::EventPathSegment.new(:a_segment,ns2).path
17
+ end
18
+ end
19
+
20
+ context "EventPathSegment#subscribe" do
21
+ should "Add the provided block to the list of subscribers" do
22
+ seg = Wonkavision::EventPathSegment.new
23
+ x = 1
24
+ seg.subscribe {x+=1 }
25
+ assert_equal 1, seg.subscribers.length
26
+ seg.subscribers[0].call
27
+ assert_equal 2, x
28
+ end
29
+ end
30
+
31
+ context "EventPathSegment#notifiy_subscribers" do
32
+ should "call each subscribed block" do
33
+ seg = Wonkavision::EventPathSegment.new
34
+ x = 1
35
+ seg.subscribe {x+=1}
36
+ seg.subscribe {|data,path|x+=data+path}
37
+ seg.notify_subscribers(5,2)
38
+
39
+ assert_equal 9, x
40
+ end
41
+ end
56
42
  end