chickadee 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/chickadee.gemspec +2 -2
  3. data/lib/chickadee/dispatcher.rb +32 -0
  4. data/lib/chickadee/dispatchers/command_dispatcher.rb +19 -0
  5. data/lib/chickadee/dispatchers/dispatcher_manager.rb +47 -0
  6. data/lib/chickadee/dispatchers/event_dispatcher.rb +22 -0
  7. data/lib/chickadee/dispatchers/handler_chain_struct.rb +17 -0
  8. data/lib/chickadee/dispatchers/message_bus.rb +65 -0
  9. data/lib/chickadee/dispatchers/query_dispatcher.rb +18 -0
  10. data/lib/chickadee/dispatchers/request_dispatcher.rb +21 -0
  11. data/lib/chickadee/exceptions.rb +2 -1
  12. data/lib/chickadee/requests/command.rb +4 -0
  13. data/lib/chickadee/requests/event.rb +4 -0
  14. data/lib/chickadee/requests/query.rb +4 -0
  15. data/lib/chickadee/{request.rb → requests/request.rb} +5 -1
  16. data/lib/chickadee/version.rb +1 -1
  17. data/lib/chickadee.rb +12 -7
  18. data/spec/dispatchers/command_dispatcher_spec.rb +55 -0
  19. data/spec/dispatchers/event_dispatcher_spec.rb +70 -0
  20. data/spec/dispatchers/handler_chain_struct_spec.rb +30 -0
  21. data/spec/dispatchers/message_bus_spec.rb +73 -0
  22. data/spec/dispatchers/query_dispatcher_spec.rb +57 -0
  23. data/spec/{command_spec.rb → requests/command_spec.rb} +1 -0
  24. data/spec/requests/event_spec.rb +12 -0
  25. data/spec/{query_spec.rb → requests/query_spec.rb} +1 -0
  26. metadata +32 -21
  27. data/lib/chickadee/application.rb +0 -27
  28. data/lib/chickadee/command.rb +0 -10
  29. data/lib/chickadee/handler.rb +0 -7
  30. data/lib/chickadee/query.rb +0 -10
  31. data/lib/chickadee/registry.rb +0 -19
  32. data/lib/chickadee/router.rb +0 -78
  33. data/spec/chickadee_spec.rb +0 -128
  34. data/spec/registry_spec.rb +0 -37
  35. data/spec/router_spec.rb +0 -89
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5bcb4cef05aca78538224ff2212092ab72bea7ca
4
- data.tar.gz: e93f3c823ccf6911931b6ccf3dcf314a584bcd34
3
+ metadata.gz: 2c94ac31b90bdc338d7fde56dcc3197cd5cc3dda
4
+ data.tar.gz: 0114a62df6b8770ed3e43422ad77aef00f48ba64
5
5
  SHA512:
6
- metadata.gz: b73a763034b866983accad6d7b8b4873bf75a4d623f75d024289afc81d6fc8f39f134a2fa8e26d4df18c0333f0ba3c23de67ce7ddd6070a8ae3aa2422a04f17a
7
- data.tar.gz: 5c305b328b9855a187ddaa68927630775e900fe131dcfcad1bf27e929474a1d1e7dd2d93451255999e31864febe58e49c5b502b7ee531f34b98c3ba88d94e2a2
6
+ metadata.gz: ad5ee648a68d9274a1dbab7ca17208c266787f2e3eef24fba786ab3837ad7670555deabd2d4cfd39e05ff6a452fb47769e613d9f98f8deeb5e05604a489aa814
7
+ data.tar.gz: 2d3b5eaa405012bc49a44f2ac29a309cbecbf8ed7c52318dd7e3c22b50a0c94b5504893a8150c15b4a8e72bf08cbf22cad56e1159b558470169be58dd6391340
data/chickadee.gemspec CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "ioc", "~> 0.5.0"
21
+ spec.add_dependency "ioc", "~> 2.1.0"
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
24
  spec.add_development_dependency "rake"
25
25
  spec.add_development_dependency "mocha", "~> 0.14.0"
26
- end
26
+ end
@@ -0,0 +1,32 @@
1
+ module Chickadee
2
+ class Dispatcher
3
+ def self.install(*installers)
4
+ [*installers].inject(new) do |d, installer|
5
+ installer.install(d)
6
+ d
7
+ end
8
+ end
9
+
10
+ def initialize
11
+ @container = Container.new
12
+ @dispatcher_manager = DispatcherManager.new(
13
+ CommandDispatcher.new(@container),
14
+ QueryDispatcher.new(@container),
15
+ EventDispatcher.new(@container),
16
+ )
17
+ @container.register(:event_dispatcher, @dispatcher_manager.event_dispatcher, :as => :instance)
18
+ end
19
+
20
+ def register(*args)
21
+ @container.register(*args)
22
+ end
23
+
24
+ def map(*args)
25
+ @dispatcher_manager.map(*args)
26
+ end
27
+
28
+ def dispatch(*args)
29
+ @dispatcher_manager.dispatch(*args)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,19 @@
1
+ module Chickadee
2
+ class CommandDispatcher < RequestDispatcher
3
+ def map(request_key, *handlers)
4
+ raise(DispatcherError, "Command already mapped: #{request_key}") if bus.topic_exists?(request_key)
5
+ bus.subscribe(request_key) {|req| resolve_handler_chain(*handlers).handle(req)}
6
+ end
7
+
8
+ def dispatch(request)
9
+ bus.publish(request.class, request)
10
+ nil
11
+ end
12
+
13
+ private
14
+
15
+ def bus
16
+ @bus ||= MessageBus.new
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,47 @@
1
+ module Chickadee
2
+ class DispatcherManager
3
+
4
+ attr_reader :command_dispatcher, :query_dispatcher, :event_dispatcher
5
+
6
+ def initialize(container, command_dispatcher, query_dispatcher, event_dispatcher)
7
+ @container = container
8
+ @command_dispatcher = command_dispatcher
9
+ @event_dispatcher = event_dispatcher
10
+ @query_dispatcher = query_dispatcher
11
+ end
12
+
13
+ def map(request_key, *handlers)
14
+ send("map_#{request_key.type}", request_key, *handlers)
15
+ end
16
+
17
+ def dispatch(request)
18
+ send("dispatch_#{request.class.type}", request)
19
+ end
20
+
21
+ private
22
+
23
+ def map_command(*args)
24
+ @command_dispatcher.map(*args)
25
+ end
26
+
27
+ def map_query(*args)
28
+ @query_dispatcher.map(*args)
29
+ end
30
+
31
+ def map_event(*args)
32
+ @event_dispatcher.map(*args)
33
+ end
34
+
35
+ def dispatch_command(*args)
36
+ @command_dispatcher.dispatch(*args)
37
+ end
38
+
39
+ def dispatch_query(*args)
40
+ @query_dispatcher.dispatch(*args)
41
+ end
42
+
43
+ def dispatch_event(*args)
44
+ @event_dispatcher.dispatch(*args)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,22 @@
1
+ module Chickadee
2
+ class EventDispatcher < RequestDispatcher
3
+ def map(request_key, *handlers)
4
+ bus.subscribe(request_key) {|req| resolve_handler_chain(*handlers).handle(req)}
5
+ end
6
+
7
+ def dispatch(request)
8
+ bus.publish(request.class, request)
9
+ nil
10
+ end
11
+
12
+ def raise(*args)
13
+ dispatch(*args)
14
+ end
15
+
16
+ private
17
+
18
+ def bus
19
+ @bus ||= MessageBus.new
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ module Chickadee
2
+ class HandlerChainStruct
3
+ def self.new(*parameter_names, &block)
4
+ klass = Class.new(&block)
5
+ klass.class_eval <<-EOT, __FILE__, __LINE__ + 1
6
+ def initialize(#{parameter_names.map(&:to_s).join(", ")}) # def initialize(user_repo, session_repo)
7
+ @handlers = [#{parameter_names.map(&:to_s).join(", ")}] # @handlers = [user_repo, session_repo]
8
+ end # end
9
+
10
+ def handle(request)
11
+ @handlers.map {|h| h.handle(request)}.last
12
+ end
13
+ EOT
14
+ klass
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,65 @@
1
+ module Chickadee
2
+ class MessageBus
3
+ class Topic
4
+ attr_reader :subscribers
5
+
6
+ def initialize
7
+ @subscribers = []
8
+ end
9
+
10
+ def subscribe(obj)
11
+ @subscribers << obj
12
+ end
13
+
14
+ def unsubscribe(subscriber_id)
15
+ @subscribers.delete_if{|subscriber| subscriber.id == subscriber_id}
16
+ end
17
+ end
18
+
19
+ class Subscriber
20
+ attr_reader :id
21
+
22
+ def initialize(id, &block)
23
+ @id = id
24
+ @block = block
25
+ end
26
+
27
+ def call(*args)
28
+ @block.call(*args)
29
+ end
30
+ end
31
+
32
+ def initialize
33
+ @topics = {}
34
+ @subscriber_id = -1
35
+ end
36
+
37
+ def subscribe(topic_key, &block)
38
+ subscriber = Subscriber.new(next_subscriber_id, &block)
39
+ get_topic(topic_key).subscribe(subscriber)
40
+ subscriber.id
41
+ end
42
+
43
+ def unsubscribe(subscriber_id)
44
+ @topics.each {|topic_key, topic| topic.unsubscribe(subscriber_id)}
45
+ end
46
+
47
+ def publish(topic_key, *args)
48
+ get_topic(topic_key).subscribers.each {|s| s.call(*args)}
49
+ end
50
+
51
+ def topic_exists?(key)
52
+ @topics.keys.include?(key)
53
+ end
54
+
55
+ private
56
+
57
+ def get_topic(topic_key)
58
+ @topics[topic_key] ||= Topic.new
59
+ end
60
+
61
+ def next_subscriber_id
62
+ @subscriber_id = @subscriber_id + 1
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,18 @@
1
+ module Chickadee
2
+ class QueryDispatcher < RequestDispatcher
3
+ def map(request_key, *handlers)
4
+ raise(DispatcherError, "Query already mapped: #{request_key}") if cache.key?(request_key)
5
+ cache[request_key] = Proc.new{|req| resolve_handler_chain(*handlers).handle(req)}
6
+ end
7
+
8
+ def dispatch(request)
9
+ cache[request.class].call(request)
10
+ end
11
+
12
+ private
13
+
14
+ def cache
15
+ @cache ||= {}
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module Chickadee
2
+ class RequestDispatcher
3
+ def initialize(container)
4
+ @container = container
5
+ end
6
+
7
+ def map(request_key, *handlers)
8
+ raise(NotImplementedError)
9
+ end
10
+
11
+ def dispatch(request)
12
+ raise(NotImplementedError)
13
+ end
14
+
15
+ private
16
+
17
+ def resolve_handler_chain(*handlers)
18
+ @container.resolve_anonymous(HandlerChainStruct.new(*handlers))
19
+ end
20
+ end
21
+ end
@@ -1,4 +1,5 @@
1
1
  module Chickadee
2
2
  class ChickadeeError < StandardError; end
3
- class RoutingError < ChickadeeError; end
3
+ class DispatcherError < ChickadeeError; end
4
+ class HandlerNotFound < ChickadeeError; end
4
5
  end
@@ -0,0 +1,4 @@
1
+ module Chickadee
2
+ class Command < Request
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Chickadee
2
+ class Event < Request
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Chickadee
2
+ class Query < Request
3
+ end
4
+ end
@@ -8,10 +8,14 @@ module Chickadee
8
8
  request_type == :query
9
9
  end
10
10
 
11
+ def event?
12
+ request_type == :event
13
+ end
14
+
11
15
  private
12
16
 
13
17
  def request_type
14
- raise(NotImplementedError)
18
+ self.class.name.split('::').last.downcase.to_sym
15
19
  end
16
20
  end
17
21
  end
@@ -1,3 +1,3 @@
1
1
  module Chickadee
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/chickadee.rb CHANGED
@@ -2,13 +2,18 @@ require 'ioc'
2
2
  require 'chickadee/version'
3
3
  require 'chickadee/exceptions'
4
4
  require 'chickadee/container'
5
- require 'chickadee/router'
6
- require 'chickadee/request'
7
- require 'chickadee/query'
8
- require 'chickadee/command'
9
- require 'chickadee/handler'
10
- require 'chickadee/registry'
11
- require 'chickadee/application'
5
+ require 'chickadee/requests/request'
6
+ require 'chickadee/requests/command'
7
+ require 'chickadee/requests/query'
8
+ require 'chickadee/requests/event'
9
+ require 'chickadee/dispatchers/handler_chain_struct'
10
+ require 'chickadee/dispatchers/message_bus'
11
+ require 'chickadee/dispatchers/request_dispatcher'
12
+ require 'chickadee/dispatchers/event_dispatcher'
13
+ require 'chickadee/dispatchers/command_dispatcher'
14
+ require 'chickadee/dispatchers/query_dispatcher'
15
+ require 'chickadee/dispatchers/dispatcher_manager'
16
+ require 'chickadee/dispatcher'
12
17
 
13
18
  module Chickadee
14
19
  end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require 'chickadee'
3
+
4
+ describe Chickadee::CommandDispatcher do
5
+ it 'can map handler chain to request' do
6
+ container = define_container
7
+ dispatcher = define_dispatcher(container)
8
+ command = Chickadee::Command.new
9
+ handler1 = stub(:handle => 'handler1_response')
10
+ handler2 = stub(:handle => 'handler2_response')
11
+
12
+ container.register(:myhandler1, handler1, :as => :instance)
13
+ container.register(:myhandler2, handler2, :as => :instance)
14
+
15
+ dispatcher.map(Chickadee::Command, :myhandler1, :myhandler2)
16
+
17
+ handler1.expects(:handle).once
18
+ handler2.expects(:handle).once
19
+ dispatcher.dispatch(command)
20
+ end
21
+
22
+ it 'complains if same command mapped twice' do
23
+ container = define_container
24
+ dispatcher = define_dispatcher(container)
25
+ command = Chickadee::Command.new
26
+
27
+ dispatcher.map(Chickadee::Command, stub)
28
+ proc{ dispatcher.map(Chickadee::Command, stub) }.must_raise(Chickadee::DispatcherError)
29
+ end
30
+
31
+ it 'returns nothing' do
32
+ container = define_container
33
+ dispatcher = define_dispatcher(container)
34
+ command = Chickadee::Command.new
35
+ handler1 = stub(:handle => 'handler1_response')
36
+
37
+ container.register(:myhandler1, handler1, :as => :instance)
38
+
39
+ dispatcher.map(Chickadee::Command, :myhandler1)
40
+ dispatcher.dispatch(command).must_be_nil
41
+ end
42
+
43
+
44
+ def define_container
45
+ Chickadee::Container.new
46
+ end
47
+
48
+ def define_dispatcher(*args)
49
+ Chickadee::CommandDispatcher.new(*args)
50
+ end
51
+
52
+ def define_command
53
+ Chickadee::Command.new
54
+ end
55
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'chickadee'
3
+
4
+ describe Chickadee::EventDispatcher do
5
+ it 'can map handler chain to request' do
6
+ container = define_container
7
+ dispatcher = define_dispatcher(container)
8
+ event = Chickadee::Event.new
9
+ handler1 = stub(:handle => 'handler1_response')
10
+ handler2 = stub(:handle => 'handler2_response')
11
+
12
+ container.register(:myhandler1, handler1, :as => :instance)
13
+ container.register(:myhandler2, handler2, :as => :instance)
14
+
15
+ dispatcher.map(Chickadee::Event, :myhandler1, :myhandler2)
16
+
17
+ handler1.expects(:handle).once
18
+ handler2.expects(:handle).once
19
+ dispatcher.dispatch(event)
20
+ end
21
+
22
+ it 'can map multiple handler chains to request' do
23
+ container = define_container
24
+ dispatcher = define_dispatcher(container)
25
+ event = Chickadee::Event.new
26
+ handler1 = stub(:handle => 'handler1_response')
27
+ handler2 = stub(:handle => 'handler2_response')
28
+ handler3 = stub(:handle => 'handler3_response')
29
+ handler4 = stub(:handle => 'handler4_response')
30
+
31
+ container.register(:myhandler1, handler1, :as => :instance)
32
+ container.register(:myhandler2, handler2, :as => :instance)
33
+ container.register(:myhandler3, handler3, :as => :instance)
34
+ container.register(:myhandler4, handler4, :as => :instance)
35
+
36
+ dispatcher.map(Chickadee::Event, :myhandler1, :myhandler2)
37
+ dispatcher.map(Chickadee::Event, :myhandler3, :myhandler4)
38
+
39
+ handler1.expects(:handle).once
40
+ handler2.expects(:handle).once
41
+ handler3.expects(:handle).once
42
+ handler4.expects(:handle).once
43
+ dispatcher.dispatch(event)
44
+ end
45
+
46
+ it 'returns nothing' do
47
+ container = define_container
48
+ dispatcher = define_dispatcher(container)
49
+ event = Chickadee::Event.new
50
+ handler1 = stub(:handle => 'handler1_response')
51
+
52
+ container.register(:myhandler1, handler1, :as => :instance)
53
+
54
+ dispatcher.map(Chickadee::Event, :myhandler1)
55
+ dispatcher.dispatch(event).must_be_nil
56
+ end
57
+
58
+
59
+ def define_container
60
+ Chickadee::Container.new
61
+ end
62
+
63
+ def define_dispatcher(*args)
64
+ Chickadee::EventDispatcher.new(*args)
65
+ end
66
+
67
+ def define_event
68
+ Chickadee::Event.new
69
+ end
70
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'chickadee'
3
+
4
+ describe Chickadee::HandlerChainStruct do
5
+ it 'generates handler class' do
6
+ person_class1 = struct_class.new(:first_name, :last_name)
7
+ person_class2 = struct_class.new(:first_name, :last_name)
8
+ person_class1.wont_equal(person_class2)
9
+ end
10
+
11
+ describe 'instance' do
12
+ describe '#handle' do
13
+ it 'delegates handle method to handlers in chain' do
14
+ request = stub
15
+ handler1 = stub
16
+ handler2 = stub
17
+ handler_chain_class = struct_class.new(:handler1, :handler2)
18
+ handler_chain = handler_chain_class.new(handler1, handler2)
19
+
20
+ handler1.expects(:handle).with(request)
21
+ handler2.expects(:handle).with(request)
22
+ handler_chain.handle(request)
23
+ end
24
+ end
25
+ end
26
+
27
+ def struct_class
28
+ Chickadee::HandlerChainStruct
29
+ end
30
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ require 'chickadee'
3
+
4
+ describe Chickadee::MessageBus do
5
+ it 'can register block with bus topic' do
6
+ bus = new_bus
7
+
8
+ output = nil
9
+
10
+ bus.subscribe("topic") do |msg|
11
+ output = msg
12
+ end
13
+
14
+ output.must_be_nil
15
+ bus.publish("topic", 'the proc was called')
16
+ output.must_equal('the proc was called')
17
+ end
18
+
19
+ it 'can pubish a message for a given topic' do
20
+ bus = new_bus
21
+
22
+ output1 = nil
23
+ output2 = nil
24
+
25
+ bus.subscribe("topic1") { |msg| output1 = msg }
26
+ bus.subscribe("topic2") { |msg| output2 = msg }
27
+
28
+ bus.publish("topic1", 'message for topic1')
29
+ bus.publish("topic2", 'message for topic2')
30
+
31
+ output1.must_equal('message for topic1')
32
+ output2.must_equal('message for topic2')
33
+ end
34
+
35
+ it 'can unsubscribe a listener' do
36
+ bus = new_bus
37
+
38
+ output = nil
39
+ subscriber_id = bus.subscribe("topic") { |msg| output = msg }
40
+
41
+ bus.publish("topic", 'i received the message')
42
+ output.must_equal('i received the message')
43
+
44
+ bus.publish("topic", 'i received the message a second time')
45
+ output.must_equal('i received the message a second time')
46
+
47
+ bus.unsubscribe(subscriber_id)
48
+
49
+ bus.publish("topic", 'i received the message a third time')
50
+ output.must_equal('i received the message a second time')
51
+ end
52
+
53
+ it 'can publish any number of arguments' do
54
+ bus = new_bus
55
+
56
+ output1 = nil
57
+ output2 = nil
58
+
59
+ bus.subscribe("topic") do |arg1, arg2|
60
+ output1 = arg1
61
+ output2 = arg2
62
+ end
63
+
64
+ bus.publish("topic", 'myarg1', 'myarg2')
65
+
66
+ output1.must_equal('myarg1')
67
+ output2.must_equal('myarg2')
68
+ end
69
+
70
+ def new_bus
71
+ Chickadee::MessageBus.new
72
+ end
73
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+ require 'chickadee'
3
+
4
+ describe Chickadee::QueryDispatcher do
5
+ it 'can map handler chain to request' do
6
+ container = define_container
7
+ dispatcher = define_dispatcher(container)
8
+ query = Chickadee::Query.new
9
+ handler1 = stub(:handle => 'handler1_response')
10
+ handler2 = stub(:handle => 'handler2_response')
11
+
12
+ container.register(:myhandler1, handler1, :as => :instance)
13
+ container.register(:myhandler2, handler2, :as => :instance)
14
+
15
+ dispatcher.map(Chickadee::Query, :myhandler1, :myhandler2)
16
+
17
+ handler1.expects(:handle).once
18
+ handler2.expects(:handle).once
19
+ dispatcher.dispatch(query)
20
+ end
21
+
22
+ it 'complains if same query mapped twice' do
23
+ container = define_container
24
+ dispatcher = define_dispatcher(container)
25
+ query = Chickadee::Query.new
26
+
27
+ dispatcher.map(Chickadee::Query, stub)
28
+ proc{ dispatcher.map(Chickadee::Query, stub) }.must_raise(Chickadee::DispatcherError)
29
+ end
30
+
31
+ it 'returns output from last handler in chain' do
32
+ container = define_container
33
+ dispatcher = define_dispatcher(container)
34
+ query = Chickadee::Query.new
35
+ handler1 = stub(:handle => 'handler1_response')
36
+ handler2 = stub(:handle => 'handler2_response')
37
+
38
+ container.register(:myhandler1, handler1, :as => :instance)
39
+ container.register(:myhandler2, handler2, :as => :instance)
40
+
41
+ dispatcher.map(Chickadee::Query, :myhandler1, :myhandler2)
42
+ dispatcher.dispatch(query).must_equal('handler2_response')
43
+ end
44
+
45
+
46
+ def define_container
47
+ Chickadee::Container.new
48
+ end
49
+
50
+ def define_dispatcher(*args)
51
+ Chickadee::QueryDispatcher.new(*args)
52
+ end
53
+
54
+ def define_query
55
+ Chickadee::Query.new
56
+ end
57
+ end
@@ -4,6 +4,7 @@ require 'chickadee'
4
4
  describe Chickadee::Command do
5
5
  it { new_query.query?.must_equal(false) }
6
6
  it { new_query.command?.must_equal(true) }
7
+ it { new_query.event?.must_equal(false) }
7
8
 
8
9
  def new_query
9
10
  Chickadee::Command.new
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'chickadee'
3
+
4
+ describe Chickadee::Event do
5
+ it { new_query.query?.must_equal(false) }
6
+ it { new_query.command?.must_equal(false) }
7
+ it { new_query.event?.must_equal(true) }
8
+
9
+ def new_query
10
+ Chickadee::Event.new
11
+ end
12
+ end
@@ -4,6 +4,7 @@ require 'chickadee'
4
4
  describe Chickadee::Query do
5
5
  it { new_query.query?.must_equal(true) }
6
6
  it { new_query.command?.must_equal(false) }
7
+ it { new_query.event?.must_equal(false) }
7
8
 
8
9
  def new_query
9
10
  Chickadee::Query.new
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chickadee
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Lott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-08 00:00:00.000000000 Z
11
+ date: 2014-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ioc
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.0
19
+ version: 2.1.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.5.0
26
+ version: 2.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -81,21 +81,29 @@ files:
81
81
  - Rakefile
82
82
  - chickadee.gemspec
83
83
  - lib/chickadee.rb
84
- - lib/chickadee/application.rb
85
- - lib/chickadee/command.rb
86
84
  - lib/chickadee/container.rb
85
+ - lib/chickadee/dispatcher.rb
86
+ - lib/chickadee/dispatchers/command_dispatcher.rb
87
+ - lib/chickadee/dispatchers/dispatcher_manager.rb
88
+ - lib/chickadee/dispatchers/event_dispatcher.rb
89
+ - lib/chickadee/dispatchers/handler_chain_struct.rb
90
+ - lib/chickadee/dispatchers/message_bus.rb
91
+ - lib/chickadee/dispatchers/query_dispatcher.rb
92
+ - lib/chickadee/dispatchers/request_dispatcher.rb
87
93
  - lib/chickadee/exceptions.rb
88
- - lib/chickadee/handler.rb
89
- - lib/chickadee/query.rb
90
- - lib/chickadee/registry.rb
91
- - lib/chickadee/request.rb
92
- - lib/chickadee/router.rb
94
+ - lib/chickadee/requests/command.rb
95
+ - lib/chickadee/requests/event.rb
96
+ - lib/chickadee/requests/query.rb
97
+ - lib/chickadee/requests/request.rb
93
98
  - lib/chickadee/version.rb
94
- - spec/chickadee_spec.rb
95
- - spec/command_spec.rb
96
- - spec/query_spec.rb
97
- - spec/registry_spec.rb
98
- - spec/router_spec.rb
99
+ - spec/dispatchers/command_dispatcher_spec.rb
100
+ - spec/dispatchers/event_dispatcher_spec.rb
101
+ - spec/dispatchers/handler_chain_struct_spec.rb
102
+ - spec/dispatchers/message_bus_spec.rb
103
+ - spec/dispatchers/query_dispatcher_spec.rb
104
+ - spec/requests/command_spec.rb
105
+ - spec/requests/event_spec.rb
106
+ - spec/requests/query_spec.rb
99
107
  - spec/spec_helper.rb
100
108
  homepage: ''
101
109
  licenses:
@@ -122,9 +130,12 @@ signing_key:
122
130
  specification_version: 4
123
131
  summary: Lightweight domain driven design library
124
132
  test_files:
125
- - spec/chickadee_spec.rb
126
- - spec/command_spec.rb
127
- - spec/query_spec.rb
128
- - spec/registry_spec.rb
129
- - spec/router_spec.rb
133
+ - spec/dispatchers/command_dispatcher_spec.rb
134
+ - spec/dispatchers/event_dispatcher_spec.rb
135
+ - spec/dispatchers/handler_chain_struct_spec.rb
136
+ - spec/dispatchers/message_bus_spec.rb
137
+ - spec/dispatchers/query_dispatcher_spec.rb
138
+ - spec/requests/command_spec.rb
139
+ - spec/requests/event_spec.rb
140
+ - spec/requests/query_spec.rb
130
141
  - spec/spec_helper.rb
@@ -1,27 +0,0 @@
1
- module Chickadee
2
- class Application
3
- def self.routes
4
- @router ||= Router.new
5
- end
6
-
7
- def self.registry
8
- @internal_registry ||= Registry.new
9
- end
10
-
11
- def initialize
12
- @external_registry = Registry.new
13
- end
14
-
15
- def call(request)
16
- container = Container.new
17
- self.class.registry.update_container(container)
18
- @external_registry.update_container(container)
19
- output = self.class.routes.call(request.class).map{|handler| container[handler].handle(request)}.last
20
- output if request.query?
21
- end
22
-
23
- def register(name, service)
24
- @external_registry.register(name, service, :as => :instance)
25
- end
26
- end
27
- end
@@ -1,10 +0,0 @@
1
- module Chickadee
2
- class Command < Request
3
-
4
- private
5
-
6
- def request_type
7
- :command
8
- end
9
- end
10
- end
@@ -1,7 +0,0 @@
1
- module Chickadee
2
- class Handler
3
- def handle(request)
4
- raise(NotImplementedError)
5
- end
6
- end
7
- end
@@ -1,10 +0,0 @@
1
- module Chickadee
2
- class Query < Request
3
-
4
- private
5
-
6
- def request_type
7
- :query
8
- end
9
- end
10
- end
@@ -1,19 +0,0 @@
1
- module Chickadee
2
- class Registry
3
- def initialize
4
- @registrants = []
5
- end
6
-
7
- def draw(&block)
8
- instance_eval(&block) if block_given?
9
- end
10
-
11
- def register(*args)
12
- @registrants << args
13
- end
14
-
15
- def update_container(container)
16
- @registrants.each{|args| container.register(*args)}
17
- end
18
- end
19
- end
@@ -1,78 +0,0 @@
1
- module Chickadee
2
- class Router
3
- class RequestMap
4
- def initialize(map = {})
5
- @map = map
6
- end
7
-
8
- def call(request)
9
- if @map.key?(request)
10
- @map.fetch(request).call(request)
11
- else
12
- app = @map[:app]
13
- raise(RoutingError, 'missing run statement') unless app
14
- app.call(request)
15
- end
16
- end
17
- end
18
-
19
- class Middleware
20
- def initialize(app, handler)
21
- @app = app
22
- @handler = handler
23
- end
24
-
25
- def call(request)
26
- @app.call(request).unshift(@handler)
27
- end
28
- end
29
-
30
- def initialize(default_app = nil, &block)
31
- @run = default_app
32
- @use = []
33
- @map = nil
34
- instance_eval(&block) if block_given?
35
- end
36
-
37
- def draw(&block)
38
- instance_eval(&block) if block_given?
39
- end
40
-
41
- def use(handler, &block)
42
- if @map
43
- mapping = @map
44
- @map = nil
45
- @use << proc { |app| generate_map(app, mapping) }
46
- end
47
- @use << proc { |app| Middleware.new(app, handler, &block) }
48
- end
49
-
50
- def run(handler)
51
- @run = proc{|request| [handler]}
52
- end
53
-
54
- def map(method_name, &block)
55
- @map ||= {}
56
- @map[method_name] = block
57
- end
58
-
59
- def to_app
60
- app = @map ? generate_map(@run, @map) : @run
61
- raise(RoutingError, 'missing run or map statement') unless app
62
- app = @use.reverse.inject(app) { |a,e| e[a] }
63
- app
64
- end
65
-
66
- def call(request)
67
- to_app.call(request)
68
- end
69
-
70
- private
71
-
72
- def generate_map(default_app, mapping)
73
- mapped = default_app ? {:app => default_app} : {}
74
- mapping.each { |r,b| mapped[r] = self.class.new(default_app, &b) }
75
- RequestMap.new(mapped)
76
- end
77
- end
78
- end
@@ -1,128 +0,0 @@
1
- require 'spec_helper'
2
- require 'chickadee'
3
-
4
- describe Chickadee do
5
-
6
- class TestCommand1 < Chickadee::Command
7
- attr_accessor :name
8
- end
9
-
10
- class TestQuery1 < Chickadee::Query
11
- attr_accessor :name
12
- end
13
-
14
- class TestHandler1 < Chickadee::Handler
15
- def handle(command)
16
- "hander1 says: #{command.name}"
17
- end
18
- end
19
-
20
- class TestHandler2 < Chickadee::Handler
21
- def handle(command)
22
- "hander2 says: #{command.name}"
23
- end
24
- end
25
-
26
- context 'when command request' do
27
- it 'returns nil from command' do
28
- app_class = new_app_class
29
- app_class.routes.draw do
30
- map(TestCommand1) do
31
- run :handler1
32
- end
33
- end
34
- app_class.registry.draw do
35
- register(:handler1, TestHandler1)
36
- end
37
-
38
- app = app_class.new
39
- command = TestCommand1.new
40
- command.name = 'Chuck Norris'
41
- app.call(command).must_be_nil
42
- end
43
-
44
- it 'executes handler chain' do
45
- app_class = new_app_class
46
-
47
- handler1 = TestHandler1.new
48
- handler2 = TestHandler2.new
49
-
50
- app_class.routes.draw do
51
- map(TestCommand1) do
52
- use :handler1
53
- run :handler2
54
- end
55
- end
56
-
57
- app_class.registry.draw do
58
- register(:handler1, handler1, :as => :instance)
59
- register(:handler2, handler2, :as => :instance)
60
- end
61
-
62
- app = app_class.new
63
- command = TestCommand1.new
64
-
65
- handler1.expects(:handle).with(command)
66
- handler2.expects(:handle).with(command)
67
-
68
- app.call(command)
69
- end
70
- end
71
-
72
- context 'when query request' do
73
- it 'returns output from last handler in handler chain' do
74
- app_class = new_app_class
75
-
76
- handler1 = TestHandler1.new
77
- handler2 = TestHandler2.new
78
-
79
- app_class.routes.draw do
80
- map(TestQuery1) do
81
- use :handler1
82
- run :handler2
83
- end
84
- end
85
-
86
- app_class.registry.draw do
87
- register(:handler1, handler1, :as => :instance)
88
- register(:handler2, handler2, :as => :instance)
89
- end
90
-
91
- app = app_class.new
92
- query = TestQuery1.new
93
- query.name = 'Chuck Norris'
94
- app.call(query).must_equal('hander2 says: Chuck Norris')
95
- end
96
-
97
- it 'executes handler chain' do
98
- app_class = new_app_class
99
-
100
- handler1 = TestHandler1.new
101
- handler2 = TestHandler2.new
102
-
103
- app_class.routes.draw do
104
- map(TestQuery1) do
105
- use :handler1
106
- run :handler2
107
- end
108
- end
109
-
110
- app_class.registry.draw do
111
- register(:handler1, handler1, :as => :instance)
112
- register(:handler2, handler2, :as => :instance)
113
- end
114
-
115
- app = app_class.new
116
- query = TestQuery1.new
117
-
118
- handler1.expects(:handle).with(query)
119
- handler2.expects(:handle).with(query)
120
-
121
- app.call(query)
122
- end
123
- end
124
-
125
- def new_app_class
126
- Class.new(Chickadee::Application)
127
- end
128
- end
@@ -1,37 +0,0 @@
1
- require 'spec_helper'
2
- require 'chickadee'
3
-
4
- describe Chickadee::Registry do
5
- describe '#update_container' do
6
- it 'updates container with registered services' do
7
- registry = new_registry
8
- service = stub
9
- container = new_container
10
-
11
- registry.register(:myservice, service, :as => :instance)
12
- registry.update_container(container)
13
- container.resolve(:myservice).must_equal(service)
14
- end
15
- end
16
-
17
- describe '#draw' do
18
- it 'can register with block' do
19
- registry = new_registry
20
- service = stub
21
-
22
- registry.draw do
23
- register(:service, service)
24
- end
25
-
26
- registry.instance_variable_get(:@registrants).must_equal([[:service, service]])
27
- end
28
- end
29
-
30
- def new_registry
31
- Chickadee::Registry.new
32
- end
33
-
34
- def new_container
35
- Chickadee::Container.new
36
- end
37
- end
data/spec/router_spec.rb DELETED
@@ -1,89 +0,0 @@
1
- require 'spec_helper'
2
- require 'chickadee'
3
-
4
- describe Chickadee::Router do
5
- it 'chains handlers' do
6
- request = stub
7
-
8
- app = builder do
9
- use :handler1
10
- run :handler2
11
- end
12
-
13
- app.call(request).must_equal([:handler1, :handler2])
14
- end
15
-
16
- it 'supports use after run' do
17
- request = stub
18
- app = builder do
19
- use :handler1
20
- run :handler2
21
- use :handler3
22
- end
23
-
24
- app.call(request).must_equal([:handler1, :handler3, :handler2])
25
- end
26
-
27
- it 'complains when there is no run' do
28
- request = stub
29
- app = builder do
30
- use :handler1
31
- end
32
-
33
- proc { app.call(request) }.must_raise(Chickadee::RoutingError)
34
- end
35
-
36
- it 'supports mapping' do
37
- request = stub
38
- app = builder do
39
- map(request) do
40
- use :handler1
41
- run :handler2
42
- end
43
- end
44
-
45
- app.call(request).must_equal([:handler1, :handler2])
46
- end
47
-
48
- it 'complains when there is no run with mapping' do
49
- request = stub
50
- app = builder do
51
- use :handler1
52
- map(request) do
53
- use :handler2
54
- end
55
- end
56
-
57
- proc { app.call(request) }.must_raise(Chickadee::RoutingError)
58
- end
59
-
60
- it 'correctly maps complex senario' do
61
- request1 = stub
62
- request2 = stub
63
-
64
- app = builder do
65
- use :handler1
66
-
67
- map(request1) do
68
- use :handler2
69
- run :handler3
70
- end
71
-
72
- use :handler4
73
-
74
- map(request2) do
75
- use :handler5
76
- end
77
-
78
- run :handler6
79
- end
80
-
81
- app.call(request1).must_equal([:handler1, :handler2, :handler3])
82
- app.call(request2).must_equal([:handler1, :handler4, :handler5, :handler6])
83
- app.call(nil).must_equal([:handler1, :handler4, :handler6])
84
- end
85
-
86
- def builder(&block)
87
- Chickadee::Router.new(&block)
88
- end
89
- end