serf 0.9.0 → 0.10.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/lib/serf/serfer.rb CHANGED
@@ -1,145 +1,87 @@
1
- require 'active_support/core_ext/hash/keys'
1
+ require 'hashie'
2
2
 
3
3
  require 'serf/error'
4
+ require 'serf/errors/not_found'
4
5
  require 'serf/util/error_handling'
6
+ require 'serf/util/null_object'
5
7
 
6
8
  module Serf
7
9
 
10
+ ##
11
+ # Class to drive the command handler execution, error handling, etc
12
+ # of received messages.
8
13
  class Serfer
9
- include ::Serf::Util::ErrorHandling
14
+ include Serf::Util::ErrorHandling
15
+
16
+ attr_reader :route_set
17
+ attr_reader :response_channel
18
+ attr_reader :error_channel
19
+ attr_reader :logger
10
20
 
11
21
  def initialize(*args)
12
22
  extract_options! args
13
23
 
14
- # Map of Runners to Registries
15
- @registries = opts :registries, {}
16
-
17
- # Additional serf infrastructure options to pass to Endpoints#build.
18
- @serf_options = opts :serf_options, {}
19
-
20
- # Options for handling the requests
21
- @not_found = opts :not_found, lambda { |env|
22
- raise ArgumentError, 'Handler Not Found'
23
- }
24
+ @route_set = opts! :route_set
25
+ @response_channel = opts(:response_channel) { Serf::Util::NullObject }
26
+ @error_channel = opts(:error_channel) { Serf::Util::NullObject }
27
+ @logger = opts(:logger) { Serf::Util::NullObject }
24
28
  end
25
29
 
26
30
  ##
27
31
  # Rack-like call to run a set of handlers for a message
28
32
  #
29
33
  def call(env)
30
- # We normalize by symbolizing the env keys
31
- env = env.symbolize_keys
32
-
33
- # Call the processor
34
- matched, results = process_request env
35
-
36
- # If we don't have any handlers, do the not_found call.
37
- # NOTE: Purposefully not wrapping this in exception handling.
38
- return @not_found.call env unless matched > 0
39
-
34
+ env = Hashie::Mash.new env unless env.is_a? Hashie::Mash
35
+
36
+ # We normalize by making the request a Hashie Mash
37
+ message = Hashie::Mash.new env.message
38
+ context = Hashie::Mash.new env.context
39
+
40
+ # Resolve the routes that we want to run
41
+ routes = route_set.resolve message, context
42
+
43
+ # We raise an error if no routes were found.
44
+ raise Serf::Errors::NotFound unless routes.size > 0
45
+
46
+ # For each route, we're going to execute
47
+ results = routes.map { |route|
48
+ # 1. Check request+context with the policies (RAISE)
49
+ # 2. Execute command (RETURNS Hash)
50
+ ok, res = with_error_handling(
51
+ message: message,
52
+ options: context) do
53
+ route.check_policies! message, context
54
+ route.execute! message, context
55
+ end
56
+ # Return the run_results as result of this block.
57
+ res
58
+ }.flatten.select { |r| r }
59
+ push_results results, context
40
60
  return results
41
61
  rescue => e
42
- e.extend(::Serf::Error)
62
+ e.extend(Serf::Error)
43
63
  raise e
44
64
  end
45
- alias_method :push, :call
46
- alias_method :<<, :call
47
65
 
48
- def self.build(options={})
49
- self.new options
66
+ def self.build(*args, &block)
67
+ new *args, &block
50
68
  end
51
69
 
52
- protected
70
+ private
53
71
 
54
72
  ##
55
- # Do the work of processing the env.
56
- # 1. Match our endpoints to run, keep associated with their runner.
57
- # 2. Turn endpoints into actual handlers that can be called by runners.
58
- # 3. Call runner to process the endpoints
59
- # 4. Return results
60
- #
61
- # NOTES:
62
- # * Any error in matching will be raised to the caller, not absorbed by
63
- # the error handler.
64
- # * Any error in Handler creation from endpoint will be caught by the
65
- # error handler, (1) pushed to the error channel and (2)
66
- # an error event will included in the results pass back to caller.
67
- # (a) There may be successul handlers created that can complete.
68
- # * If the runner raises an error, it will be caught and the error
69
- # event will be appended to the results. This is so one
70
- # runner failure will not affect another runner's run.
71
- # Each runner SHOULD do their own error handling so errors in
72
- # one handler will not affect another in the list of handlers the runner
73
- # is to process.
74
- # * RUNNERS MUST push errors they catch to the error channel.
75
- #
76
- def process_request(env)
77
- # This will be the work we need to do.
78
- # This is a hash of runners to handlers to run.
79
- tasks = {}
80
-
81
- # We're going to concat all the results
82
- results = []
83
-
84
- # Figure out which endpoints to run.
85
- matches = match_endpoints env
86
-
87
- # Now we go head and create our Tasks (Units of Work)
88
- # for each of the matched endpoints (with their runners).
89
- matches.each do |runner, endpoints|
90
- # We create the unit of work
91
- handlers = endpoints.map{ |endpoint|
92
- # We try to build the endpoint. Any errors here will
93
- # be caught and returned to the caller.
94
- # This is so individual building of tasks do not affect other tasks.
95
- ok, obj = with_error_handling(env) do
96
- endpoint.build env.dup, @serf_options
97
- end
98
- # The return of this if/else statement will be result of map item.
99
- if ok
100
- obj
101
- else
102
- results << obj
103
- nil
104
- end
105
- }.
106
- select{ |h| !h.nil? }
107
-
108
- # No we enqueue the units of work into our task queue
109
- # List could be empty because all build calls could have error out.
110
- tasks[runner] = handlers if handlers.size > 0
111
- end
112
-
113
- # We call the runners with the handlers they need to execute.
114
- # Errors raised by the runner are pushed to the error channel.
115
- # Errors here are also passed back the caller of the SerfApp.
116
- #
117
- tasks.each do |runner, handlers|
118
- ok, run_result = with_error_handling(env) do
119
- runner.call handlers, env
73
+ # Loop over the results and push them to the response channel.
74
+ # Any error in pushing individual messages will result in
75
+ # a log event and an error channel event.
76
+ def push_results(results, context)
77
+ results.each do |result|
78
+ with_error_handling(result) do
79
+ response_channel.push(
80
+ message: result,
81
+ context: context)
120
82
  end
121
- # We need to coerce the runner's results (nil, Hash, Array, Object)
122
- # into an Array of messages.
123
- # now we concat this run's results to our total results list.
124
- run_result = run_result.is_a?(Hash) ? [run_result] : Array(run_result)
125
- results.concat run_result
126
83
  end
127
-
128
- return matches.size, results
129
- end
130
-
131
- ##
132
- # Figure out which endpoints to run
133
- #
134
- def match_endpoints(env)
135
- matches = {}
136
-
137
- @registries.each do |runner, registry|
138
- endpoints = registry.match env
139
- matches[runner] = endpoints if endpoints.size > 0
140
- end
141
-
142
- return matches
84
+ return nil
143
85
  end
144
86
 
145
87
  end
@@ -22,13 +22,9 @@ module Util
22
22
  ##
23
23
  # A block wrapper to handle errors when executing a block.
24
24
  #
25
- def with_error_handling(context=nil, errback=:handle_error, &block)
26
- ok, results = protected_call &block
27
- return ok, (ok ?
28
- results :
29
- ((errback.is_a?(Proc) ?
30
- errback.call(results, context) :
31
- send(errback, results, context))))
25
+ def with_error_handling(context=nil, *args, &block)
26
+ ok, results = pcall *args, &block
27
+ return ok, (ok ? results : handle_error(results, context))
32
28
  end
33
29
 
34
30
  ##
@@ -38,8 +34,8 @@ module Util
38
34
  # log the exception itself to the logger.
39
35
  #
40
36
  def handle_error(e, context=nil)
41
- logger = opts :logger, ::Serf::Util::NullObject.new
42
- error_channel = opts :error_channel, ::Serf::Util::NullObject.new
37
+ logger = opts(:logger){ ::Serf::Util::NullObject.new }
38
+ error_channel = opts(:error_channel) { ::Serf::Util::NullObject.new }
43
39
  error_event = {
44
40
  kind: 'serf/messages/caught_exception_event',
45
41
  context: context,
@@ -1,3 +1,5 @@
1
+ require 'hashie'
2
+
1
3
  module Serf
2
4
  module Util
3
5
 
@@ -29,7 +31,7 @@ module Util
29
31
  # Reader method for the options hash.
30
32
  #
31
33
  def options
32
- return @options || {}
34
+ return @options || Hashie::Mash.new
33
35
  end
34
36
 
35
37
  ##
@@ -92,12 +94,21 @@ module Util
92
94
  protected
93
95
 
94
96
  ##
95
- # Extracts the options from the arguments list.
97
+ # Extracts the options from the arguments list, BUT does not save it to
98
+ # an instance variable for use by the opts helpr methods.
99
+ #
100
+ def pop_options!(args)
101
+ args.last.is_a?(::Hash) ?
102
+ [true, Hashie::Mash.new(args.pop)] :
103
+ [false, Hashie::Mash.new]
104
+ end
105
+
106
+ ##
107
+ # Extracts the options from the arguments list, and saves it to the
108
+ # an instance variable for use by the opts helpr methods.
96
109
  #
97
110
  def extract_options!(args)
98
- _, @options = args.last.is_a?(::Hash) ?
99
- [true, args.pop.dup] :
100
- [false, {}]
111
+ _, @options = pop_options! args
101
112
  end
102
113
 
103
114
  end
@@ -23,11 +23,12 @@ module Util
23
23
  #
24
24
  # @return boolean success and the block's (or caught exception) results.
25
25
  #
26
- def protected_call
27
- return true, yield
26
+ def pcall(*args)
27
+ return true, yield(*args)
28
28
  rescue => e
29
29
  return false, e
30
30
  end
31
+ alias_method :protected_call, :pcall
31
32
 
32
33
  end
33
34
 
@@ -1,4 +1,5 @@
1
1
  require 'base64'
2
+ require 'hashie'
2
3
  require 'uuidtools'
3
4
 
4
5
  module Serf
@@ -12,6 +13,30 @@ module Util
12
13
  #
13
14
  module Uuidable
14
15
 
16
+ ##
17
+ # @see self.create_coded_uuid
18
+ def create_coded_uuid
19
+ Uuidable.create_coded_uuid
20
+ end
21
+
22
+ ##
23
+ # @see self.parse_coded_uuid
24
+ def parse_coded_uuid(coded_uuid)
25
+ Uuidable.parse_coded_uuid coded_uuid
26
+ end
27
+
28
+ ##
29
+ # @see self.create_uuids
30
+ def create_uuids(parent={})
31
+ Uuidable.create_uuids parent
32
+ end
33
+
34
+ ##
35
+ # @see self.annotate_with_uuids!
36
+ def annotate_with_uuids!(message, parent={})
37
+ Uuidable.annotate_with_uuids! message, parent
38
+ end
39
+
15
40
  ##
16
41
  # Creates a Timestamp UUID, base64 encoded.
17
42
  #
@@ -38,14 +63,13 @@ module Util
38
63
  # Create a new set of uuids.
39
64
  #
40
65
  def self.create_uuids(parent={})
41
- {
66
+ Hashie::Mash.new(
42
67
  uuid: create_coded_uuid,
43
- parent_uuid: parent['uuid'],
68
+ parent_uuid: parent[:uuid],
44
69
  origin_uuid: (
45
70
  parent[:origin_uuid] ||
46
71
  parent[:parent_uuid] ||
47
- parent[:uuid])
48
- }
72
+ parent[:uuid]))
49
73
  end
50
74
 
51
75
  ##
data/lib/serf/version.rb CHANGED
@@ -2,7 +2,7 @@ module Serf
2
2
 
3
3
  module Version
4
4
  MAJOR = 0
5
- MINOR = 9
5
+ MINOR = 10
6
6
  PATCH = 0
7
7
  BUILD = nil
8
8
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join '.'
data/serf.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "serf"
8
- s.version = "0.9.0"
8
+ s.version = "0.10.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Benjamin Yu"]
12
- s.date = "2012-05-06"
12
+ s.date = "2012-05-30"
13
13
  s.description = "Event-Driven SOA with CQRS"
14
14
  s.email = "benjaminlyu@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -30,21 +30,18 @@ Gem::Specification.new do |s|
30
30
  "lib/serf/builder.rb",
31
31
  "lib/serf/command.rb",
32
32
  "lib/serf/error.rb",
33
+ "lib/serf/errors/not_found.rb",
34
+ "lib/serf/middleware/girl_friday_async.rb",
35
+ "lib/serf/middleware/masherize.rb",
33
36
  "lib/serf/middleware/uuid_tagger.rb",
34
- "lib/serf/more/command_worker.rb",
35
- "lib/serf/routing/endpoint.rb",
36
- "lib/serf/routing/registry.rb",
37
- "lib/serf/runners/direct.rb",
38
- "lib/serf/runners/event_machine.rb",
39
- "lib/serf/runners/girl_friday.rb",
40
- "lib/serf/runners/helper.rb",
37
+ "lib/serf/routing/regexp_matcher.rb",
38
+ "lib/serf/routing/route.rb",
39
+ "lib/serf/routing/route_set.rb",
41
40
  "lib/serf/serfer.rb",
42
41
  "lib/serf/util/error_handling.rb",
43
- "lib/serf/util/mash_factory.rb",
44
42
  "lib/serf/util/null_object.rb",
45
43
  "lib/serf/util/options_extraction.rb",
46
44
  "lib/serf/util/protected_call.rb",
47
- "lib/serf/util/regexp_matcher.rb",
48
45
  "lib/serf/util/uuidable.rb",
49
46
  "lib/serf/version.rb",
50
47
  "schemas/caught_exception_event.json",
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.9.0
4
+ version: 0.10.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-05-06 00:00:00.000000000 Z
12
+ date: 2012-05-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &70100670653360 !ruby/object:Gem::Requirement
16
+ requirement: &70327288822860 !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: *70100670653360
24
+ version_requirements: *70327288822860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: i18n
27
- requirement: &70100670652560 !ruby/object:Gem::Requirement
27
+ requirement: &70327288821320 !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: *70100670652560
35
+ version_requirements: *70327288821320
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: hashie
38
- requirement: &70100670651180 !ruby/object:Gem::Requirement
38
+ requirement: &70327288843640 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.2.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70100670651180
46
+ version_requirements: *70327288843640
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: uuidtools
49
- requirement: &70100670649260 !ruby/object:Gem::Requirement
49
+ requirement: &70327288842560 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 2.1.2
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70100670649260
57
+ version_requirements: *70327288842560
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
- requirement: &70100670647520 !ruby/object:Gem::Requirement
60
+ requirement: &70327288841020 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 2.8.0
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70100670647520
68
+ version_requirements: *70327288841020
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
- requirement: &70100670646500 !ruby/object:Gem::Requirement
71
+ requirement: &70327288839480 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 0.7.5
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70100670646500
79
+ version_requirements: *70327288839480
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: bundler
82
- requirement: &70100670814180 !ruby/object:Gem::Requirement
82
+ requirement: &70327288837820 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 1.1.3
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70100670814180
90
+ version_requirements: *70327288837820
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: jeweler
93
- requirement: &70100670813540 !ruby/object:Gem::Requirement
93
+ requirement: &70327288847420 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 1.8.3
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70100670813540
101
+ version_requirements: *70327288847420
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: simplecov
104
- requirement: &70100670812840 !ruby/object:Gem::Requirement
104
+ requirement: &70327288845020 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70100670812840
112
+ version_requirements: *70327288845020
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: log4r
115
- requirement: &70100670812100 !ruby/object:Gem::Requirement
115
+ requirement: &70327288859780 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 1.1.10
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70100670812100
123
+ version_requirements: *70327288859780
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: msgpack
126
- requirement: &70100670811380 !ruby/object:Gem::Requirement
126
+ requirement: &70327288858080 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: 0.4.6
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *70100670811380
134
+ version_requirements: *70327288858080
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: eventmachine
137
- requirement: &70100670810700 !ruby/object:Gem::Requirement
137
+ requirement: &70327288857320 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ! '>='
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: 0.12.10
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *70100670810700
145
+ version_requirements: *70327288857320
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: girl_friday
148
- requirement: &70100670809960 !ruby/object:Gem::Requirement
148
+ requirement: &70327288856640 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ! '>='
@@ -153,7 +153,7 @@ dependencies:
153
153
  version: 0.9.7
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *70100670809960
156
+ version_requirements: *70327288856640
157
157
  description: Event-Driven SOA with CQRS
158
158
  email: benjaminlyu@gmail.com
159
159
  executables: []
@@ -175,21 +175,18 @@ files:
175
175
  - lib/serf/builder.rb
176
176
  - lib/serf/command.rb
177
177
  - lib/serf/error.rb
178
+ - lib/serf/errors/not_found.rb
179
+ - lib/serf/middleware/girl_friday_async.rb
180
+ - lib/serf/middleware/masherize.rb
178
181
  - lib/serf/middleware/uuid_tagger.rb
179
- - lib/serf/more/command_worker.rb
180
- - lib/serf/routing/endpoint.rb
181
- - lib/serf/routing/registry.rb
182
- - lib/serf/runners/direct.rb
183
- - lib/serf/runners/event_machine.rb
184
- - lib/serf/runners/girl_friday.rb
185
- - lib/serf/runners/helper.rb
182
+ - lib/serf/routing/regexp_matcher.rb
183
+ - lib/serf/routing/route.rb
184
+ - lib/serf/routing/route_set.rb
186
185
  - lib/serf/serfer.rb
187
186
  - lib/serf/util/error_handling.rb
188
- - lib/serf/util/mash_factory.rb
189
187
  - lib/serf/util/null_object.rb
190
188
  - lib/serf/util/options_extraction.rb
191
189
  - lib/serf/util/protected_call.rb
192
- - lib/serf/util/regexp_matcher.rb
193
190
  - lib/serf/util/uuidable.rb
194
191
  - lib/serf/version.rb
195
192
  - schemas/caught_exception_event.json
@@ -212,7 +209,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
212
209
  version: '0'
213
210
  segments:
214
211
  - 0
215
- hash: 2754574147578555547
212
+ hash: 2408210682612837552
216
213
  required_rubygems_version: !ruby/object:Gem::Requirement
217
214
  none: false
218
215
  requirements:
@@ -1,45 +0,0 @@
1
- require 'serf/command'
2
- require 'serf/util/error_handling'
3
-
4
- module Serf
5
- module More
6
-
7
- ##
8
- # Creates a proc (CommandWorker.worker) that will be used by
9
- # GirlFriday WorkQueues. This proc will receive messages from
10
- # GirlFriday and will (1) create a CommandWorker instance with the
11
- # given message and (2) execute (#call) said CommandWorker instance.
12
- # The CommandWorker instance assumes that the received message is
13
- # a callable (#call) object, and will execute that object's 'call' method.
14
- #
15
- # The purpose of this is so we can build Command objects in one
16
- # context/thread and have it actually executed in a separate threadpool.
17
- #
18
- # Example:
19
- #
20
- # # Creates the GirlFriday work queue.
21
- # command_worker_queue = GirlFriday::WorkQueue.new(
22
- # CommandWorker.worker(
23
- # logger: my_logger,
24
- # response_channel: response_channel,
25
- # error_channel: error_channel))
26
- #
27
- # # In some place that receives requests and generates commands.
28
- # # Push the command into the command workqueue for async processing.
29
- # command_worker_queue.push MyCommand.build(REQUEST_HASH)
30
- #
31
- class CommandWorker
32
- include Serf::Command
33
- include Serf::ErrorHandling
34
-
35
- def call
36
- ok, results = with_error_handling do
37
- request.call
38
- end
39
- return results
40
- end
41
-
42
- end
43
-
44
- end
45
- end