serf 0.6.1 → 0.7.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.
- data/Gemfile +10 -4
- data/Gemfile.lock +27 -17
- data/README.md +317 -120
- data/docs/thread_pools.txt +16 -0
- data/lib/serf/builder.rb +126 -162
- data/lib/serf/command.rb +113 -0
- data/lib/serf/message.rb +16 -2
- data/lib/serf/messages/caught_exception_event.rb +10 -7
- data/lib/serf/routing/endpoint.rb +49 -0
- data/lib/serf/routing/registry.rb +66 -0
- data/lib/serf/runners/direct.rb +52 -0
- data/lib/serf/runners/event_machine.rb +71 -0
- data/lib/serf/runners/girl_friday.rb +73 -0
- data/lib/serf/runners/helper.rb +23 -0
- data/lib/serf/serfer.rb +112 -25
- data/lib/serf/util/{with_error_handling.rb → error_handling.rb} +23 -10
- data/lib/serf/util/options_extraction.rb +106 -0
- data/lib/serf/version.rb +2 -2
- data/serf.gemspec +31 -20
- metadata +60 -33
- data/lib/serf/runners/direct_runner.rb +0 -60
- data/lib/serf/runners/em_runner.rb +0 -62
- data/lib/serf/util/route_endpoint.rb +0 -37
- data/lib/serf/util/route_set.rb +0 -82
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &70285339872700 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.2.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70285339872700
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: i18n
|
27
|
-
requirement: &
|
27
|
+
requirement: &70285339872080 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.6.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70285339872080
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: uuidtools
|
38
|
-
requirement: &
|
38
|
+
requirement: &70285339871240 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,54 +43,54 @@ dependencies:
|
|
43
43
|
version: 2.1.2
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70285339871240
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &70285339870220 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 2.
|
54
|
+
version: 2.8.0
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70285339870220
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: yard
|
60
|
-
requirement: &
|
60
|
+
requirement: &70285339869440 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version: 0.
|
65
|
+
version: 0.7.5
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70285339869440
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: bundler
|
71
|
-
requirement: &
|
71
|
+
requirement: &70285339868840 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: 1.0.
|
76
|
+
version: 1.0.22
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70285339868840
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: jeweler
|
82
|
-
requirement: &
|
82
|
+
requirement: &70285339868260 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
86
86
|
- !ruby/object:Gem::Version
|
87
|
-
version: 1.
|
87
|
+
version: 1.8.3
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70285339868260
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: simplecov
|
93
|
-
requirement: &
|
93
|
+
requirement: &70285339867680 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,21 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70285339867680
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: log4r
|
104
|
+
requirement: &70285339866960 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.1.10
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70285339866960
|
102
113
|
- !ruby/object:Gem::Dependency
|
103
114
|
name: msgpack
|
104
|
-
requirement: &
|
115
|
+
requirement: &70285339866280 !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
107
118
|
- - ! '>='
|
@@ -109,10 +120,10 @@ dependencies:
|
|
109
120
|
version: 0.4.6
|
110
121
|
type: :development
|
111
122
|
prerelease: false
|
112
|
-
version_requirements: *
|
123
|
+
version_requirements: *70285339866280
|
113
124
|
- !ruby/object:Gem::Dependency
|
114
125
|
name: eventmachine
|
115
|
-
requirement: &
|
126
|
+
requirement: &70285339914940 !ruby/object:Gem::Requirement
|
116
127
|
none: false
|
117
128
|
requirements:
|
118
129
|
- - ! '>='
|
@@ -120,7 +131,18 @@ dependencies:
|
|
120
131
|
version: 0.12.10
|
121
132
|
type: :development
|
122
133
|
prerelease: false
|
123
|
-
version_requirements: *
|
134
|
+
version_requirements: *70285339914940
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: girl_friday
|
137
|
+
requirement: &70285339914320 !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ~>
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.9.7
|
143
|
+
type: :development
|
144
|
+
prerelease: false
|
145
|
+
version_requirements: *70285339914320
|
124
146
|
description: Event-Driven SOA with CQRS
|
125
147
|
email: benjaminlyu@gmail.com
|
126
148
|
executables: []
|
@@ -137,22 +159,27 @@ files:
|
|
137
159
|
- NOTICE.txt
|
138
160
|
- README.md
|
139
161
|
- Rakefile
|
162
|
+
- docs/thread_pools.txt
|
140
163
|
- lib/serf.rb
|
141
164
|
- lib/serf/builder.rb
|
165
|
+
- lib/serf/command.rb
|
142
166
|
- lib/serf/error.rb
|
143
167
|
- lib/serf/message.rb
|
144
168
|
- lib/serf/messages/caught_exception_event.rb
|
145
169
|
- lib/serf/messages/message_accepted_event.rb
|
146
170
|
- lib/serf/middleware/uuid_tagger.rb
|
147
|
-
- lib/serf/
|
148
|
-
- lib/serf/
|
171
|
+
- lib/serf/routing/endpoint.rb
|
172
|
+
- lib/serf/routing/registry.rb
|
173
|
+
- lib/serf/runners/direct.rb
|
174
|
+
- lib/serf/runners/event_machine.rb
|
175
|
+
- lib/serf/runners/girl_friday.rb
|
176
|
+
- lib/serf/runners/helper.rb
|
149
177
|
- lib/serf/serfer.rb
|
178
|
+
- lib/serf/util/error_handling.rb
|
150
179
|
- lib/serf/util/null_object.rb
|
180
|
+
- lib/serf/util/options_extraction.rb
|
151
181
|
- lib/serf/util/regexp_matcher.rb
|
152
|
-
- lib/serf/util/route_endpoint.rb
|
153
|
-
- lib/serf/util/route_set.rb
|
154
182
|
- lib/serf/util/uuidable.rb
|
155
|
-
- lib/serf/util/with_error_handling.rb
|
156
183
|
- lib/serf/version.rb
|
157
184
|
- serf.gemspec
|
158
185
|
- spec/serf_spec.rb
|
@@ -172,7 +199,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
172
199
|
version: '0'
|
173
200
|
segments:
|
174
201
|
- 0
|
175
|
-
hash:
|
202
|
+
hash: 314755585934468655
|
176
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
204
|
none: false
|
178
205
|
requirements:
|
@@ -181,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
208
|
version: '0'
|
182
209
|
requirements: []
|
183
210
|
rubyforge_project:
|
184
|
-
rubygems_version: 1.8.
|
211
|
+
rubygems_version: 1.8.17
|
185
212
|
signing_key:
|
186
213
|
specification_version: 3
|
187
214
|
summary: Event-Driven SOA with CQRS
|
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'serf/util/with_error_handling'
|
2
|
-
|
3
|
-
module Serf
|
4
|
-
module Runners
|
5
|
-
|
6
|
-
##
|
7
|
-
# Direct runner drives the execution of a handler for given messages.
|
8
|
-
# This class deals with error handling and publishing handler results
|
9
|
-
# to proper error or results channels.
|
10
|
-
#
|
11
|
-
class DirectRunner
|
12
|
-
include ::Serf::Util::WithErrorHandling
|
13
|
-
|
14
|
-
def initialize(options={})
|
15
|
-
# Mandatory, we want both results and error channels.
|
16
|
-
@results_channel = options.fetch(:results_channel)
|
17
|
-
@error_channel = options.fetch(:error_channel)
|
18
|
-
|
19
|
-
# Optional overrides for error handling
|
20
|
-
@error_event_class = options[:error_event_class]
|
21
|
-
@logger = options[:logger]
|
22
|
-
end
|
23
|
-
|
24
|
-
def run(endpoints, env)
|
25
|
-
results = []
|
26
|
-
endpoints.each do |ep|
|
27
|
-
run_results = with_error_handling(env) do
|
28
|
-
params = ep.message_parser ? ep.message_parser.parse(env) : env
|
29
|
-
ep.handler.send(ep.action, params)
|
30
|
-
end
|
31
|
-
results.concat Array(run_results)
|
32
|
-
publish_results run_results
|
33
|
-
end
|
34
|
-
return results
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.build(options={})
|
38
|
-
self.new options
|
39
|
-
end
|
40
|
-
|
41
|
-
protected
|
42
|
-
|
43
|
-
##
|
44
|
-
# Loop over the results and publish them to the results channel.
|
45
|
-
# Any error in publishing individual messages will result in
|
46
|
-
# a log event and an error channel event.
|
47
|
-
def publish_results(results)
|
48
|
-
results = Array(results)
|
49
|
-
results.each do |message|
|
50
|
-
with_error_handling(message) do
|
51
|
-
@results_channel.publish message
|
52
|
-
end
|
53
|
-
end
|
54
|
-
return nil
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
|
3
|
-
require 'serf/messages/message_accepted_event'
|
4
|
-
require 'serf/runners/direct_runner'
|
5
|
-
|
6
|
-
module Serf
|
7
|
-
module Runners
|
8
|
-
|
9
|
-
##
|
10
|
-
# This runner simply wraps another runner to execute in the
|
11
|
-
# EventMachine deferred threadpool.
|
12
|
-
#
|
13
|
-
# NOTE: Because the Serfer class validates messages before
|
14
|
-
# sending them to runners (and handlers), this class simply
|
15
|
-
# responds to the calling client with an 'MessageAcceptedEvent'
|
16
|
-
# to signal that the message will be processed later.
|
17
|
-
#
|
18
|
-
# Errors caught here will simply be logged. This is because
|
19
|
-
# the wrapped runner *MUST* handle its own errors. If an error
|
20
|
-
# should propagate up here, then it was most likely an error
|
21
|
-
# that occurred in a rescue block... we don't want to complicate
|
22
|
-
# any extra publishing to error channels because that may have
|
23
|
-
# been the cause of the error.
|
24
|
-
#
|
25
|
-
class EmRunner
|
26
|
-
|
27
|
-
def initialize(options={})
|
28
|
-
# Manditory: Need a runner because EmRunner is just a wrapper.
|
29
|
-
@runner = options.fetch(:runner)
|
30
|
-
|
31
|
-
@mae_class = options.fetch(:message_accepted_event_class) {
|
32
|
-
::Serf::Messages::MessageAcceptedEvent
|
33
|
-
}
|
34
|
-
@evm = options.fetch(:event_machine) { ::EventMachine }
|
35
|
-
@logger = options.fetch(:logger) { ::Serf::Util::NullObject.new }
|
36
|
-
end
|
37
|
-
|
38
|
-
def run(endpoints, env)
|
39
|
-
endpoints = endpoints.dup
|
40
|
-
env = env.dup
|
41
|
-
@evm.defer(proc do
|
42
|
-
begin
|
43
|
-
@runner.run endpoints, env
|
44
|
-
rescue => e
|
45
|
-
@logger.error "#{e.inspect}\n\n#{e.backtrace.join("\n")}"
|
46
|
-
end
|
47
|
-
end)
|
48
|
-
return @mae_class.new message: env
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.build(options={})
|
52
|
-
options[:runner] = options.fetch(:runner) {
|
53
|
-
factory = options[:runner_factory] || ::Serf::Runners::DirectRunner
|
54
|
-
factory.build options
|
55
|
-
}
|
56
|
-
self.new options
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
62
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Serf
|
2
|
-
module Util
|
3
|
-
|
4
|
-
##
|
5
|
-
# A simple class to represent route endpoints. RouteSets
|
6
|
-
# store a list of endpoints per matcher, and Runners use endpoints
|
7
|
-
# to then execute the handlers.
|
8
|
-
#
|
9
|
-
class RouteEndpoint
|
10
|
-
# Actual handler object that defines the action method.
|
11
|
-
attr_accessor :handler
|
12
|
-
# The method to call.
|
13
|
-
attr_accessor :action
|
14
|
-
# A parser that turns the message ENV hash into a Message object
|
15
|
-
# that the handler#action uses.
|
16
|
-
attr_accessor :message_parser
|
17
|
-
|
18
|
-
def initialize(options={})
|
19
|
-
# Mandatory parameters
|
20
|
-
@handler = options.fetch :handler
|
21
|
-
@action = options.fetch :action
|
22
|
-
|
23
|
-
# Optional parameters
|
24
|
-
@message_parser = options[:message_parser]
|
25
|
-
end
|
26
|
-
|
27
|
-
##
|
28
|
-
# Default factory method.
|
29
|
-
#
|
30
|
-
def self.build(options={})
|
31
|
-
return self.new options
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
end
|
data/lib/serf/util/route_set.rb
DELETED
@@ -1,82 +0,0 @@
|
|
1
|
-
require 'serf/util/route_endpoint'
|
2
|
-
require 'serf/util/regexp_matcher'
|
3
|
-
|
4
|
-
module Serf
|
5
|
-
module Util
|
6
|
-
|
7
|
-
##
|
8
|
-
# RouteSets hold routing information for ENV hashes to matched endpoints.
|
9
|
-
#
|
10
|
-
class RouteSet
|
11
|
-
|
12
|
-
def initialize(options={})
|
13
|
-
@routes = {}
|
14
|
-
@matchers = []
|
15
|
-
@regexp_matcher_factory = options.fetch(:regexp_matcher_factory) {
|
16
|
-
::Serf::Util::RegexpMatcher
|
17
|
-
}
|
18
|
-
@route_endpoint_factory = options.fetch(:route_endpoint_factory) {
|
19
|
-
::Serf::Util::RouteEndpoint
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
##
|
24
|
-
# Connects a matcher (String or an Object implementing ===) to an endpoint.
|
25
|
-
#
|
26
|
-
# @option opts [Obj, String] :matcher Matches ENV Hashes to endpoints.
|
27
|
-
# Note that String and Regexp values are set up to match the
|
28
|
-
# :kind key from ENV Hashes.
|
29
|
-
# @option opts [Obj] :handler Receiver of the action.
|
30
|
-
# @option opts [Symbol, String] :action Method to call on handler.
|
31
|
-
# @option opts [#parse] :message_parser Translates ENV Hash to Message Obj.
|
32
|
-
#
|
33
|
-
def add_route(options={})
|
34
|
-
# We create our endpoint representation.
|
35
|
-
endpoint = @route_endpoint_factory.build(
|
36
|
-
handler: options.fetch(:handler),
|
37
|
-
action: options.fetch(:action),
|
38
|
-
message_parser: options[:message_parser])
|
39
|
-
|
40
|
-
# Maybe we have an non-String matcher. Handle the Regexp case.
|
41
|
-
# We only keep track of matchers if it isn't a string because
|
42
|
-
# string matchers are just pulled out of routes by key lookup.
|
43
|
-
matcher = options.fetch :matcher
|
44
|
-
matcher = @regexp_matcher_factory.build matcher if matcher.kind_of? Regexp
|
45
|
-
@matchers << matcher unless matcher.is_a? String
|
46
|
-
|
47
|
-
# We add the route (matcher+endpoint) into our routes
|
48
|
-
@routes[matcher] ||= []
|
49
|
-
@routes[matcher] << endpoint
|
50
|
-
end
|
51
|
-
|
52
|
-
##
|
53
|
-
# @param [Hash] env The input message environment to match for routes.
|
54
|
-
# @return [Array] List of endpoints that matched.
|
55
|
-
#
|
56
|
-
def match_routes(env={})
|
57
|
-
kind = env[:kind]
|
58
|
-
routes = []
|
59
|
-
routes.concat Array(@routes[kind])
|
60
|
-
@matchers.each do |matcher|
|
61
|
-
routes.concat Array(@routes[matcher]) if matcher === env
|
62
|
-
end
|
63
|
-
return routes
|
64
|
-
end
|
65
|
-
|
66
|
-
##
|
67
|
-
# @return [Integer] Number of routes this RouteSet tracks.
|
68
|
-
#
|
69
|
-
def size
|
70
|
-
return @routes.size
|
71
|
-
end
|
72
|
-
|
73
|
-
##
|
74
|
-
# Default factory method.
|
75
|
-
#
|
76
|
-
def self.build(options={})
|
77
|
-
self.new options
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
end
|