serf 0.8.0 → 0.9.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 +4 -3
- data/Gemfile.lock +5 -3
- data/README.md +20 -87
- data/lib/serf/command.rb +11 -8
- data/lib/serf/middleware/uuid_tagger.rb +1 -2
- data/lib/serf/more/command_worker.rb +0 -6
- data/lib/serf/runners/event_machine.rb +4 -6
- data/lib/serf/runners/girl_friday.rb +4 -8
- data/lib/serf/util/error_handling.rb +5 -6
- data/lib/serf/util/mash_factory.rb +18 -0
- data/lib/serf/util/uuidable.rb +27 -2
- data/lib/serf/version.rb +1 -1
- data/schemas/caught_exception_event.json +21 -0
- data/schemas/message_accepted_event.json +14 -0
- data/serf.gemspec +17 -15
- metadata +44 -34
- data/lib/serf/message.rb +0 -56
- data/lib/serf/messages/caught_exception_event.rb +0 -49
- data/lib/serf/messages/message_accepted_event.rb +0 -38
- data/lib/serf/more/uuid_fields.rb +0 -29
data/Gemfile
CHANGED
@@ -6,6 +6,7 @@ source 'http://rubygems.org'
|
|
6
6
|
# Requirements for both clients and servers.
|
7
7
|
gem 'activesupport', '>= 3.2.0'
|
8
8
|
gem 'i18n', '>= 0.6.0' # For ActiveSupport
|
9
|
+
gem 'hashie', ">= 1.2.0"
|
9
10
|
# Used by Serf::Messages::*
|
10
11
|
gem 'uuidtools', '>= 2.1.2'
|
11
12
|
|
@@ -14,12 +15,12 @@ gem 'uuidtools', '>= 2.1.2'
|
|
14
15
|
group :development, :test do
|
15
16
|
gem "rspec", "~> 2.8.0"
|
16
17
|
gem "yard", "~> 0.7.5"
|
17
|
-
gem "bundler", "~> 1.
|
18
|
+
gem "bundler", "~> 1.1.3"
|
18
19
|
gem "jeweler", "~> 1.8.3"
|
19
20
|
gem 'simplecov', '>= 0'
|
20
21
|
|
21
22
|
# For our testing
|
22
|
-
gem 'log4r', '
|
23
|
+
gem 'log4r', '>= 1.1.10'
|
23
24
|
|
24
25
|
# Soft Dependencies
|
25
26
|
#gem 'log4r', '~> 1.1.9'
|
@@ -30,5 +31,5 @@ group :development, :test do
|
|
30
31
|
|
31
32
|
# EventMachine is now optional runner
|
32
33
|
gem 'eventmachine', '>= 0.12.10'
|
33
|
-
gem 'girl_friday', '
|
34
|
+
gem 'girl_friday', '>= 0.9.7'
|
34
35
|
end
|
data/Gemfile.lock
CHANGED
@@ -10,6 +10,7 @@ GEM
|
|
10
10
|
girl_friday (0.9.7)
|
11
11
|
connection_pool (~> 0.1.0)
|
12
12
|
git (1.2.5)
|
13
|
+
hashie (1.2.0)
|
13
14
|
i18n (0.6.0)
|
14
15
|
jeweler (1.8.3)
|
15
16
|
bundler (~> 1.0)
|
@@ -43,12 +44,13 @@ PLATFORMS
|
|
43
44
|
|
44
45
|
DEPENDENCIES
|
45
46
|
activesupport (>= 3.2.0)
|
46
|
-
bundler (~> 1.
|
47
|
+
bundler (~> 1.1.3)
|
47
48
|
eventmachine (>= 0.12.10)
|
48
|
-
girl_friday (
|
49
|
+
girl_friday (>= 0.9.7)
|
50
|
+
hashie (>= 1.2.0)
|
49
51
|
i18n (>= 0.6.0)
|
50
52
|
jeweler (~> 1.8.3)
|
51
|
-
log4r (
|
53
|
+
log4r (>= 1.1.10)
|
52
54
|
msgpack (>= 0.4.6)
|
53
55
|
rspec (~> 2.8.0)
|
54
56
|
simplecov
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ Messages are the representation of data, documents, etc that are
|
|
21
21
|
marshalled from client to service, which represents the business
|
22
22
|
level interaction of the service.
|
23
23
|
|
24
|
-
Messages may be
|
24
|
+
Messages may be command requests that a service must handle.
|
25
25
|
Messages may be events that a service emits.
|
26
26
|
Messages may be documents that represent state or business data.
|
27
27
|
|
@@ -59,54 +59,23 @@ Not implemented as yet:
|
|
59
59
|
Service Libraries
|
60
60
|
=================
|
61
61
|
|
62
|
-
1. Service Libraries SHOULD implement
|
63
|
-
|
64
|
-
a.
|
65
|
-
|
62
|
+
1. Service Libraries SHOULD implement messages as just hashes with
|
63
|
+
defined schemas (JSON Schema).
|
64
|
+
a. Required by all messages is the 'kind' field.
|
65
|
+
b. By default, Serf Commands will read in hashes and turn them into
|
66
|
+
more convenient Hashie::Mash objects.
|
66
67
|
2. Serialization of the messages SHOULD BE Json or MessagePack (I hate XML).
|
67
|
-
a.
|
68
|
+
a. Serf Builder will create Serf Apps that expect a HASH ENV as input
|
68
69
|
3. Handlers MUST implement the 'build' class method, which
|
69
70
|
MUST receive the ENV Hash as the first parameter, followed by supplemental
|
70
71
|
arguments as declared in the DSL.
|
71
72
|
4. Handler methods SHOULD return zero or more messages.
|
72
73
|
a. Raised errors are caught and pushed to error channels.
|
74
|
+
b. Returned messages MUST be Hash based objects for Serialization.
|
73
75
|
5. Handler methods SHOULD handle catch their business logic exceptions and
|
74
76
|
return them as specialized messages that can be forwarded down error channels.
|
75
77
|
Uncaught exceptions that are then caught by Serf are pushed as
|
76
|
-
generic
|
77
|
-
|
78
|
-
|
79
|
-
Serf::Message
|
80
|
-
-------------
|
81
|
-
|
82
|
-
Users of the Serf::Message module need to be aware of that:
|
83
|
-
|
84
|
-
1. Messages MUST implement the `#attributes` method to use the
|
85
|
-
default implementations of `to_msgpack`, `to_json`, and `to_hash`.
|
86
|
-
2. Messages MAY implement validation helpers (e.g. ActiveModel or
|
87
|
-
Virtus + Aequitas (DataMapper)). This is purely to be helpful for
|
88
|
-
receivers (Serf::Handlers) to validate the Messages before running
|
89
|
-
code against its data. The Serf infrastructure code does not
|
90
|
-
validate the Messages; it is the job of the handler code.
|
91
|
-
3. Messages MAY override `Message.parse` class method if they want
|
92
|
-
different parsing (Message object instantiation) than
|
93
|
-
`message_class.new *args`. This parse method is called in
|
94
|
-
Serf::Handler when the handler class has defined a Message class
|
95
|
-
to be used to deserialize the ENV for a handler action method.
|
96
|
-
3. Messages MAY override `Message#kind` instance method or `Message.kind`
|
97
|
-
class method to specify a message `kind` that is different than
|
98
|
-
the tableized name of the implementing ruby class.
|
99
|
-
4. Messages MAY override `Message#to_msgpack`, `Message#to_json`, or
|
100
|
-
`Message#to_hash` to get alternate serialization.
|
101
|
-
|
102
|
-
User that opt to roll their own Message class only need to be
|
103
|
-
aware that:
|
104
|
-
|
105
|
-
1. Message classes MUST implement `Message.parse(env={})` class method
|
106
|
-
if said message class is to be used as the target object representation
|
107
|
-
of a received message (from ENV hash).
|
108
|
-
a. Serf code makes this assumption when it finds an ENV
|
109
|
-
hash that is to be parsed into a message object.
|
78
|
+
generic CaughtExceptionEvents, and are harder to deal with.
|
110
79
|
|
111
80
|
|
112
81
|
Example With GirlFriday
|
@@ -118,7 +87,6 @@ Example With GirlFriday
|
|
118
87
|
|
119
88
|
require 'serf/builder'
|
120
89
|
require 'serf/command'
|
121
|
-
require 'serf/message'
|
122
90
|
require 'serf/middleware/uuid_tagger'
|
123
91
|
require 'serf/util/options_extraction'
|
124
92
|
|
@@ -151,38 +119,20 @@ Example With GirlFriday
|
|
151
119
|
end
|
152
120
|
end
|
153
121
|
|
154
|
-
# my_lib/
|
155
|
-
|
156
|
-
# ActiveModel or Aequitas/Virtus implements.
|
157
|
-
class MyMessage
|
158
|
-
include Serf::Util::OptionsExtraction
|
159
|
-
include Serf::Message
|
160
|
-
|
161
|
-
attr_accessor :data
|
162
|
-
|
163
|
-
def initialize(*args)
|
164
|
-
extract_options! args
|
165
|
-
self.data = opts :data
|
166
|
-
end
|
122
|
+
# my_lib/my_validator.rb
|
123
|
+
class MyValidator
|
167
124
|
|
168
|
-
def
|
169
|
-
|
125
|
+
def self.validate!(data)
|
126
|
+
raise 'Data is nil' if data[:data].nil?
|
170
127
|
end
|
171
128
|
|
172
|
-
def valid?
|
173
|
-
!data.nil?
|
174
|
-
end
|
175
|
-
|
176
|
-
def full_error_messages
|
177
|
-
'Data is blank' if data.nil?
|
178
|
-
end
|
179
129
|
end
|
180
130
|
|
181
131
|
# my_lib/my_overloaded_command.rb
|
182
132
|
class MyOverloadedCommand
|
183
133
|
include Serf::Command
|
184
134
|
|
185
|
-
self.
|
135
|
+
self.request_validator = MyValidator
|
186
136
|
|
187
137
|
def initialize(*args)
|
188
138
|
super
|
@@ -304,6 +254,7 @@ Example With GirlFriday
|
|
304
254
|
end
|
305
255
|
logger.info "End Tick #{Thread.current.object_id}"
|
306
256
|
|
257
|
+
|
307
258
|
Example With EventMachine
|
308
259
|
=========================
|
309
260
|
|
@@ -313,7 +264,6 @@ Example With EventMachine
|
|
313
264
|
|
314
265
|
require 'serf/builder'
|
315
266
|
require 'serf/command'
|
316
|
-
require 'serf/message'
|
317
267
|
require 'serf/middleware/uuid_tagger'
|
318
268
|
require 'serf/util/options_extraction'
|
319
269
|
|
@@ -347,37 +297,19 @@ Example With EventMachine
|
|
347
297
|
end
|
348
298
|
|
349
299
|
# my_lib/my_message.rb
|
350
|
-
|
351
|
-
# ActiveModel or Aequitas/Virtus implements.
|
352
|
-
class MyMessage
|
353
|
-
include Serf::Util::OptionsExtraction
|
354
|
-
include Serf::Message
|
300
|
+
class MyValidator
|
355
301
|
|
356
|
-
|
357
|
-
|
358
|
-
def initialize(*args)
|
359
|
-
extract_options! args
|
360
|
-
self.data = opts :data
|
361
|
-
end
|
362
|
-
|
363
|
-
def attributes
|
364
|
-
{ 'data' => data }
|
302
|
+
def self.validate!(data)
|
303
|
+
raise 'Data Missing Error' if data[:data].nil?
|
365
304
|
end
|
366
305
|
|
367
|
-
def valid?
|
368
|
-
!data.nil?
|
369
|
-
end
|
370
|
-
|
371
|
-
def full_error_messages
|
372
|
-
'Data is blank' if data.nil?
|
373
|
-
end
|
374
306
|
end
|
375
307
|
|
376
308
|
# my_lib/my_overloaded_command.rb
|
377
309
|
class MyOverloadedCommand
|
378
310
|
include Serf::Command
|
379
311
|
|
380
|
-
self.
|
312
|
+
self.request_validator = MyValidator
|
381
313
|
|
382
314
|
def initialize(*args)
|
383
315
|
super
|
@@ -506,6 +438,7 @@ Example With EventMachine
|
|
506
438
|
end
|
507
439
|
end
|
508
440
|
|
441
|
+
|
509
442
|
Contributing to serf
|
510
443
|
====================
|
511
444
|
|
data/lib/serf/command.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require 'active_support/core_ext/class/attribute'
|
3
3
|
|
4
|
+
require 'serf/util/mash_factory'
|
4
5
|
require 'serf/util/options_extraction'
|
5
6
|
|
6
7
|
module Serf
|
@@ -14,6 +15,10 @@ module Serf
|
|
14
15
|
# # Set a default Message Parser for the class.
|
15
16
|
# self.request_factory = MySerfRequestMessage
|
16
17
|
#
|
18
|
+
# # Validate the request, like using JSON-Schema for hash
|
19
|
+
# # (or Hashie's Mash) requests.
|
20
|
+
# self.request_validator = MySerfRequestValidator
|
21
|
+
#
|
17
22
|
# def initialize(*args, &block)
|
18
23
|
# # Do some validation here, or extra parameter setting with the args
|
19
24
|
# end
|
@@ -37,6 +42,8 @@ module Serf
|
|
37
42
|
|
38
43
|
included do
|
39
44
|
class_attribute :request_factory
|
45
|
+
__send__ 'request_factory=', Serf::Util::MashFactory
|
46
|
+
class_attribute :request_validator
|
40
47
|
attr_reader :request
|
41
48
|
end
|
42
49
|
|
@@ -45,11 +52,7 @@ module Serf
|
|
45
52
|
end
|
46
53
|
|
47
54
|
def validate_request!
|
48
|
-
|
49
|
-
# request object isn't a hash.
|
50
|
-
unless request.is_a?(Hash) || request.valid?
|
51
|
-
raise ArgumentError, request.full_error_messages
|
52
|
-
end
|
55
|
+
request_validator.validate! request if request_validator
|
53
56
|
end
|
54
57
|
|
55
58
|
module ClassMethods
|
@@ -86,14 +89,14 @@ module Serf
|
|
86
89
|
# Set the request instance variable to whatever type of request we got.
|
87
90
|
obj.instance_variable_set :@request, request
|
88
91
|
|
92
|
+
# Finalize the object's construction with the rest of the args & block.
|
93
|
+
obj.__send__ :initialize, *args, &block
|
94
|
+
|
89
95
|
# Now validate that the request is ok.
|
90
96
|
# Implementing classes MAY override this method to do different
|
91
97
|
# kind of request validation.
|
92
98
|
obj.validate_request!
|
93
99
|
|
94
|
-
# Finalize the object's construction with the rest of the args & block.
|
95
|
-
obj.__send__ :initialize, *args, &block
|
96
|
-
|
97
100
|
return obj
|
98
101
|
end
|
99
102
|
|
@@ -9,7 +9,6 @@ module Middleware
|
|
9
9
|
# if the incoming request already has it.
|
10
10
|
#
|
11
11
|
class UuidTagger
|
12
|
-
include Serf::Util::Uuidable
|
13
12
|
|
14
13
|
##
|
15
14
|
# @param app the app
|
@@ -23,7 +22,7 @@ module Middleware
|
|
23
22
|
def call(env)
|
24
23
|
env = env.dup
|
25
24
|
unless env[@field.to_sym] || env[@field.to_s]
|
26
|
-
env[@field] = create_coded_uuid
|
25
|
+
env[@field] = Serf::Util::Uuidable.create_coded_uuid
|
27
26
|
end
|
28
27
|
@app.call env
|
29
28
|
end
|
@@ -39,12 +39,6 @@ module More
|
|
39
39
|
return results
|
40
40
|
end
|
41
41
|
|
42
|
-
# Overriding the Serf::Command validate_request! so it doesn't
|
43
|
-
# call #valid? on the request object. This is because the incoming
|
44
|
-
# request is another Command object itself.
|
45
|
-
def validate_request!
|
46
|
-
end
|
47
|
-
|
48
42
|
end
|
49
43
|
|
50
44
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
|
3
|
-
require 'serf/messages/message_accepted_event'
|
4
3
|
require 'serf/runners/direct'
|
5
4
|
require 'serf/util/error_handling'
|
6
5
|
|
@@ -32,10 +31,6 @@ module Runners
|
|
32
31
|
# Manditory: Need a runner because this class is just a wrapper.
|
33
32
|
@runner = opts! :runner
|
34
33
|
|
35
|
-
@mae_class = opts(
|
36
|
-
:message_accepted_event_class,
|
37
|
-
::Serf::Messages::MessageAcceptedEvent)
|
38
|
-
|
39
34
|
@evm = opts :event_machine, ::EventMachine
|
40
35
|
@logger = opts :logger, ::Serf::Util::NullObject.new
|
41
36
|
end
|
@@ -54,7 +49,10 @@ module Runners
|
|
54
49
|
end
|
55
50
|
end)
|
56
51
|
end
|
57
|
-
return
|
52
|
+
return {
|
53
|
+
kind: 'serf/messages/message_accepted_event',
|
54
|
+
message: context
|
55
|
+
}
|
58
56
|
end
|
59
57
|
|
60
58
|
def self.build(options={})
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'girl_friday'
|
2
2
|
|
3
|
-
require 'serf/messages/message_accepted_event'
|
4
3
|
require 'serf/runners/helper'
|
5
4
|
require 'serf/util/error_handling'
|
6
5
|
|
@@ -30,12 +29,6 @@ module Runners
|
|
30
29
|
end
|
31
30
|
|
32
31
|
def call(handlers, context)
|
33
|
-
# Create our accepted event before we enqueue the handlers.
|
34
|
-
mae_class = opts(
|
35
|
-
:message_accepted_event_class,
|
36
|
-
::Serf::Messages::MessageAcceptedEvent)
|
37
|
-
event = mae_class.new message: context
|
38
|
-
|
39
32
|
# Push each handler into the queue along with a copy of the context.
|
40
33
|
handlers.each do |handler|
|
41
34
|
@queue.push(
|
@@ -45,7 +38,10 @@ module Runners
|
|
45
38
|
|
46
39
|
# We got here, we succeeded pushing all the works.
|
47
40
|
# Now we return our accepted event.
|
48
|
-
return
|
41
|
+
return {
|
42
|
+
kind: 'serf/messages/message_accepted_event',
|
43
|
+
message: context
|
44
|
+
}
|
49
45
|
end
|
50
46
|
|
51
47
|
##
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/string/inflections'
|
2
2
|
|
3
|
-
require 'serf/messages/caught_exception_event'
|
4
3
|
require 'serf/util/null_object'
|
5
4
|
require 'serf/util/options_extraction'
|
6
5
|
require 'serf/util/protected_call'
|
@@ -14,7 +13,6 @@ module Util
|
|
14
13
|
#
|
15
14
|
# Including classes may have the following instance variables
|
16
15
|
# to override the default values:
|
17
|
-
# * @error_event_class - ::Serf::Messages::CaughtExceptionEvent
|
18
16
|
# * @logger - ::Serf::Util::NullObject.new
|
19
17
|
# * @error_channel - ::Serf::Util::NullObject.new
|
20
18
|
module ErrorHandling
|
@@ -40,14 +38,15 @@ module Util
|
|
40
38
|
# log the exception itself to the logger.
|
41
39
|
#
|
42
40
|
def handle_error(e, context=nil)
|
43
|
-
eec = opts :error_event_class, ::Serf::Messages::CaughtExceptionEvent
|
44
41
|
logger = opts :logger, ::Serf::Util::NullObject.new
|
45
42
|
error_channel = opts :error_channel, ::Serf::Util::NullObject.new
|
46
|
-
error_event =
|
43
|
+
error_event = {
|
44
|
+
kind: 'serf/messages/caught_exception_event',
|
47
45
|
context: context,
|
48
|
-
error: e.class.to_s.
|
46
|
+
error: e.class.to_s.underscore,
|
49
47
|
message: e.message,
|
50
|
-
backtrace: e.backtrace.join("\n")
|
48
|
+
backtrace: e.backtrace.join("\n")
|
49
|
+
}
|
51
50
|
|
52
51
|
# log the error to our logger
|
53
52
|
logger.error e
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'hashie'
|
2
|
+
|
3
|
+
module Serf
|
4
|
+
module Util
|
5
|
+
|
6
|
+
##
|
7
|
+
# A Request Factory that just coerces a REQUEST ENV hash message
|
8
|
+
# into a Hashie::Mash object for convenience key/value access.
|
9
|
+
#
|
10
|
+
module MashFactory
|
11
|
+
|
12
|
+
def self.build(message)
|
13
|
+
Hashie::Mash.new message
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/lib/serf/util/uuidable.rb
CHANGED
@@ -17,7 +17,7 @@ module Util
|
|
17
17
|
#
|
18
18
|
# NOTE: UUIDTools TimeStamp code creates a UTC based timestamp UUID.
|
19
19
|
#
|
20
|
-
def create_coded_uuid
|
20
|
+
def self.create_coded_uuid
|
21
21
|
# All raw UUIDs are 16 bytes long. Base64 lengthens the string to
|
22
22
|
# 24 bytes long. We chomp off the last two equal signs '==' to
|
23
23
|
# trim the string length to 22 bytes. This gives us an overhead
|
@@ -30,10 +30,35 @@ module Util
|
|
30
30
|
##
|
31
31
|
# @param coded_uuid a coded uuid to parse.
|
32
32
|
#
|
33
|
-
def parse_coded_uuid(coded_uuid)
|
33
|
+
def self.parse_coded_uuid(coded_uuid)
|
34
34
|
UUIDTools::UUID.parse_raw Base64.urlsafe_decode64("#{coded_uuid}==")
|
35
35
|
end
|
36
36
|
|
37
|
+
##
|
38
|
+
# Create a new set of uuids.
|
39
|
+
#
|
40
|
+
def self.create_uuids(parent={})
|
41
|
+
{
|
42
|
+
uuid: create_coded_uuid,
|
43
|
+
parent_uuid: parent['uuid'],
|
44
|
+
origin_uuid: (
|
45
|
+
parent[:origin_uuid] ||
|
46
|
+
parent[:parent_uuid] ||
|
47
|
+
parent[:uuid])
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Set a message's UUIDs with new UUIDs based on the parent's UUIDs.
|
53
|
+
#
|
54
|
+
def self.annotate_with_uuids!(message, parent={})
|
55
|
+
uuids = self.create_uuids parent
|
56
|
+
message[:uuid] ||= uuids[:uuid]
|
57
|
+
message[:parent_uuid] ||= uuids[:parent_uuid]
|
58
|
+
message[:origin_uuid] ||= uuids[:origin_uuid]
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
|
37
62
|
end
|
38
63
|
|
39
64
|
end
|
data/lib/serf/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"description": "Message Kind: serf/messages/caught_exception_event",
|
3
|
+
"type": "object",
|
4
|
+
"properties": {
|
5
|
+
"context": {
|
6
|
+
"type": "object"
|
7
|
+
},
|
8
|
+
"error": {
|
9
|
+
"type": "string"
|
10
|
+
},
|
11
|
+
"message": {
|
12
|
+
"type": "string"
|
13
|
+
},
|
14
|
+
"backtrace": {
|
15
|
+
"type": "string"
|
16
|
+
},
|
17
|
+
"uuid": {
|
18
|
+
"type": "string"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}
|
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.
|
8
|
+
s.version = "0.9.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-
|
12
|
+
s.date = "2012-05-06"
|
13
13
|
s.description = "Event-Driven SOA with CQRS"
|
14
14
|
s.email = "benjaminlyu@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -30,12 +30,8 @@ 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/message.rb",
|
34
|
-
"lib/serf/messages/caught_exception_event.rb",
|
35
|
-
"lib/serf/messages/message_accepted_event.rb",
|
36
33
|
"lib/serf/middleware/uuid_tagger.rb",
|
37
34
|
"lib/serf/more/command_worker.rb",
|
38
|
-
"lib/serf/more/uuid_fields.rb",
|
39
35
|
"lib/serf/routing/endpoint.rb",
|
40
36
|
"lib/serf/routing/registry.rb",
|
41
37
|
"lib/serf/runners/direct.rb",
|
@@ -44,12 +40,15 @@ Gem::Specification.new do |s|
|
|
44
40
|
"lib/serf/runners/helper.rb",
|
45
41
|
"lib/serf/serfer.rb",
|
46
42
|
"lib/serf/util/error_handling.rb",
|
43
|
+
"lib/serf/util/mash_factory.rb",
|
47
44
|
"lib/serf/util/null_object.rb",
|
48
45
|
"lib/serf/util/options_extraction.rb",
|
49
46
|
"lib/serf/util/protected_call.rb",
|
50
47
|
"lib/serf/util/regexp_matcher.rb",
|
51
48
|
"lib/serf/util/uuidable.rb",
|
52
49
|
"lib/serf/version.rb",
|
50
|
+
"schemas/caught_exception_event.json",
|
51
|
+
"schemas/message_accepted_event.json",
|
53
52
|
"serf.gemspec",
|
54
53
|
"spec/serf_spec.rb",
|
55
54
|
"spec/spec_helper.rb"
|
@@ -66,43 +65,46 @@ Gem::Specification.new do |s|
|
|
66
65
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
67
66
|
s.add_runtime_dependency(%q<activesupport>, [">= 3.2.0"])
|
68
67
|
s.add_runtime_dependency(%q<i18n>, [">= 0.6.0"])
|
68
|
+
s.add_runtime_dependency(%q<hashie>, [">= 1.2.0"])
|
69
69
|
s.add_runtime_dependency(%q<uuidtools>, [">= 2.1.2"])
|
70
70
|
s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
71
71
|
s.add_development_dependency(%q<yard>, ["~> 0.7.5"])
|
72
|
-
s.add_development_dependency(%q<bundler>, ["~> 1.
|
72
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.1.3"])
|
73
73
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
|
74
74
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
75
|
-
s.add_development_dependency(%q<log4r>, ["
|
75
|
+
s.add_development_dependency(%q<log4r>, [">= 1.1.10"])
|
76
76
|
s.add_development_dependency(%q<msgpack>, [">= 0.4.6"])
|
77
77
|
s.add_development_dependency(%q<eventmachine>, [">= 0.12.10"])
|
78
|
-
s.add_development_dependency(%q<girl_friday>, ["
|
78
|
+
s.add_development_dependency(%q<girl_friday>, [">= 0.9.7"])
|
79
79
|
else
|
80
80
|
s.add_dependency(%q<activesupport>, [">= 3.2.0"])
|
81
81
|
s.add_dependency(%q<i18n>, [">= 0.6.0"])
|
82
|
+
s.add_dependency(%q<hashie>, [">= 1.2.0"])
|
82
83
|
s.add_dependency(%q<uuidtools>, [">= 2.1.2"])
|
83
84
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
84
85
|
s.add_dependency(%q<yard>, ["~> 0.7.5"])
|
85
|
-
s.add_dependency(%q<bundler>, ["~> 1.
|
86
|
+
s.add_dependency(%q<bundler>, ["~> 1.1.3"])
|
86
87
|
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
87
88
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
88
|
-
s.add_dependency(%q<log4r>, ["
|
89
|
+
s.add_dependency(%q<log4r>, [">= 1.1.10"])
|
89
90
|
s.add_dependency(%q<msgpack>, [">= 0.4.6"])
|
90
91
|
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
91
|
-
s.add_dependency(%q<girl_friday>, ["
|
92
|
+
s.add_dependency(%q<girl_friday>, [">= 0.9.7"])
|
92
93
|
end
|
93
94
|
else
|
94
95
|
s.add_dependency(%q<activesupport>, [">= 3.2.0"])
|
95
96
|
s.add_dependency(%q<i18n>, [">= 0.6.0"])
|
97
|
+
s.add_dependency(%q<hashie>, [">= 1.2.0"])
|
96
98
|
s.add_dependency(%q<uuidtools>, [">= 2.1.2"])
|
97
99
|
s.add_dependency(%q<rspec>, ["~> 2.8.0"])
|
98
100
|
s.add_dependency(%q<yard>, ["~> 0.7.5"])
|
99
|
-
s.add_dependency(%q<bundler>, ["~> 1.
|
101
|
+
s.add_dependency(%q<bundler>, ["~> 1.1.3"])
|
100
102
|
s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
|
101
103
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
102
|
-
s.add_dependency(%q<log4r>, ["
|
104
|
+
s.add_dependency(%q<log4r>, [">= 1.1.10"])
|
103
105
|
s.add_dependency(%q<msgpack>, [">= 0.4.6"])
|
104
106
|
s.add_dependency(%q<eventmachine>, [">= 0.12.10"])
|
105
|
-
s.add_dependency(%q<girl_friday>, ["
|
107
|
+
s.add_dependency(%q<girl_friday>, [">= 0.9.7"])
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
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.9.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-05-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &70100670653360 !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: *70100670653360
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: i18n
|
27
|
-
requirement: &
|
27
|
+
requirement: &70100670652560 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,21 @@ dependencies:
|
|
32
32
|
version: 0.6.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70100670652560
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: hashie
|
38
|
+
requirement: &70100670651180 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.2.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70100670651180
|
36
47
|
- !ruby/object:Gem::Dependency
|
37
48
|
name: uuidtools
|
38
|
-
requirement: &
|
49
|
+
requirement: &70100670649260 !ruby/object:Gem::Requirement
|
39
50
|
none: false
|
40
51
|
requirements:
|
41
52
|
- - ! '>='
|
@@ -43,10 +54,10 @@ dependencies:
|
|
43
54
|
version: 2.1.2
|
44
55
|
type: :runtime
|
45
56
|
prerelease: false
|
46
|
-
version_requirements: *
|
57
|
+
version_requirements: *70100670649260
|
47
58
|
- !ruby/object:Gem::Dependency
|
48
59
|
name: rspec
|
49
|
-
requirement: &
|
60
|
+
requirement: &70100670647520 !ruby/object:Gem::Requirement
|
50
61
|
none: false
|
51
62
|
requirements:
|
52
63
|
- - ~>
|
@@ -54,10 +65,10 @@ dependencies:
|
|
54
65
|
version: 2.8.0
|
55
66
|
type: :development
|
56
67
|
prerelease: false
|
57
|
-
version_requirements: *
|
68
|
+
version_requirements: *70100670647520
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: yard
|
60
|
-
requirement: &
|
71
|
+
requirement: &70100670646500 !ruby/object:Gem::Requirement
|
61
72
|
none: false
|
62
73
|
requirements:
|
63
74
|
- - ~>
|
@@ -65,21 +76,21 @@ dependencies:
|
|
65
76
|
version: 0.7.5
|
66
77
|
type: :development
|
67
78
|
prerelease: false
|
68
|
-
version_requirements: *
|
79
|
+
version_requirements: *70100670646500
|
69
80
|
- !ruby/object:Gem::Dependency
|
70
81
|
name: bundler
|
71
|
-
requirement: &
|
82
|
+
requirement: &70100670814180 !ruby/object:Gem::Requirement
|
72
83
|
none: false
|
73
84
|
requirements:
|
74
85
|
- - ~>
|
75
86
|
- !ruby/object:Gem::Version
|
76
|
-
version: 1.
|
87
|
+
version: 1.1.3
|
77
88
|
type: :development
|
78
89
|
prerelease: false
|
79
|
-
version_requirements: *
|
90
|
+
version_requirements: *70100670814180
|
80
91
|
- !ruby/object:Gem::Dependency
|
81
92
|
name: jeweler
|
82
|
-
requirement: &
|
93
|
+
requirement: &70100670813540 !ruby/object:Gem::Requirement
|
83
94
|
none: false
|
84
95
|
requirements:
|
85
96
|
- - ~>
|
@@ -87,10 +98,10 @@ dependencies:
|
|
87
98
|
version: 1.8.3
|
88
99
|
type: :development
|
89
100
|
prerelease: false
|
90
|
-
version_requirements: *
|
101
|
+
version_requirements: *70100670813540
|
91
102
|
- !ruby/object:Gem::Dependency
|
92
103
|
name: simplecov
|
93
|
-
requirement: &
|
104
|
+
requirement: &70100670812840 !ruby/object:Gem::Requirement
|
94
105
|
none: false
|
95
106
|
requirements:
|
96
107
|
- - ! '>='
|
@@ -98,21 +109,21 @@ dependencies:
|
|
98
109
|
version: '0'
|
99
110
|
type: :development
|
100
111
|
prerelease: false
|
101
|
-
version_requirements: *
|
112
|
+
version_requirements: *70100670812840
|
102
113
|
- !ruby/object:Gem::Dependency
|
103
114
|
name: log4r
|
104
|
-
requirement: &
|
115
|
+
requirement: &70100670812100 !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
107
|
-
- -
|
118
|
+
- - ! '>='
|
108
119
|
- !ruby/object:Gem::Version
|
109
120
|
version: 1.1.10
|
110
121
|
type: :development
|
111
122
|
prerelease: false
|
112
|
-
version_requirements: *
|
123
|
+
version_requirements: *70100670812100
|
113
124
|
- !ruby/object:Gem::Dependency
|
114
125
|
name: msgpack
|
115
|
-
requirement: &
|
126
|
+
requirement: &70100670811380 !ruby/object:Gem::Requirement
|
116
127
|
none: false
|
117
128
|
requirements:
|
118
129
|
- - ! '>='
|
@@ -120,10 +131,10 @@ dependencies:
|
|
120
131
|
version: 0.4.6
|
121
132
|
type: :development
|
122
133
|
prerelease: false
|
123
|
-
version_requirements: *
|
134
|
+
version_requirements: *70100670811380
|
124
135
|
- !ruby/object:Gem::Dependency
|
125
136
|
name: eventmachine
|
126
|
-
requirement: &
|
137
|
+
requirement: &70100670810700 !ruby/object:Gem::Requirement
|
127
138
|
none: false
|
128
139
|
requirements:
|
129
140
|
- - ! '>='
|
@@ -131,18 +142,18 @@ dependencies:
|
|
131
142
|
version: 0.12.10
|
132
143
|
type: :development
|
133
144
|
prerelease: false
|
134
|
-
version_requirements: *
|
145
|
+
version_requirements: *70100670810700
|
135
146
|
- !ruby/object:Gem::Dependency
|
136
147
|
name: girl_friday
|
137
|
-
requirement: &
|
148
|
+
requirement: &70100670809960 !ruby/object:Gem::Requirement
|
138
149
|
none: false
|
139
150
|
requirements:
|
140
|
-
- -
|
151
|
+
- - ! '>='
|
141
152
|
- !ruby/object:Gem::Version
|
142
153
|
version: 0.9.7
|
143
154
|
type: :development
|
144
155
|
prerelease: false
|
145
|
-
version_requirements: *
|
156
|
+
version_requirements: *70100670809960
|
146
157
|
description: Event-Driven SOA with CQRS
|
147
158
|
email: benjaminlyu@gmail.com
|
148
159
|
executables: []
|
@@ -164,12 +175,8 @@ files:
|
|
164
175
|
- lib/serf/builder.rb
|
165
176
|
- lib/serf/command.rb
|
166
177
|
- lib/serf/error.rb
|
167
|
-
- lib/serf/message.rb
|
168
|
-
- lib/serf/messages/caught_exception_event.rb
|
169
|
-
- lib/serf/messages/message_accepted_event.rb
|
170
178
|
- lib/serf/middleware/uuid_tagger.rb
|
171
179
|
- lib/serf/more/command_worker.rb
|
172
|
-
- lib/serf/more/uuid_fields.rb
|
173
180
|
- lib/serf/routing/endpoint.rb
|
174
181
|
- lib/serf/routing/registry.rb
|
175
182
|
- lib/serf/runners/direct.rb
|
@@ -178,12 +185,15 @@ files:
|
|
178
185
|
- lib/serf/runners/helper.rb
|
179
186
|
- lib/serf/serfer.rb
|
180
187
|
- lib/serf/util/error_handling.rb
|
188
|
+
- lib/serf/util/mash_factory.rb
|
181
189
|
- lib/serf/util/null_object.rb
|
182
190
|
- lib/serf/util/options_extraction.rb
|
183
191
|
- lib/serf/util/protected_call.rb
|
184
192
|
- lib/serf/util/regexp_matcher.rb
|
185
193
|
- lib/serf/util/uuidable.rb
|
186
194
|
- lib/serf/version.rb
|
195
|
+
- schemas/caught_exception_event.json
|
196
|
+
- schemas/message_accepted_event.json
|
187
197
|
- serf.gemspec
|
188
198
|
- spec/serf_spec.rb
|
189
199
|
- spec/spec_helper.rb
|
@@ -202,7 +212,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
202
212
|
version: '0'
|
203
213
|
segments:
|
204
214
|
- 0
|
205
|
-
hash:
|
215
|
+
hash: 2754574147578555547
|
206
216
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
207
217
|
none: false
|
208
218
|
requirements:
|
data/lib/serf/message.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'active_support/concern'
|
2
|
-
require 'active_support/core_ext/class/attribute'
|
3
|
-
require 'active_support/core_ext/string/inflections'
|
4
|
-
|
5
|
-
module Serf
|
6
|
-
|
7
|
-
##
|
8
|
-
# A module to represent a message that we're transporting over
|
9
|
-
# the wire. This is mainly for commands and events in ED-SOA.
|
10
|
-
# Optional, but useful for validations, etc.
|
11
|
-
#
|
12
|
-
module Message
|
13
|
-
extend ActiveSupport::Concern
|
14
|
-
|
15
|
-
included do
|
16
|
-
class_attribute :kind
|
17
|
-
send 'kind=', self.to_s.tableize.singularize
|
18
|
-
class_attribute :model_name
|
19
|
-
send 'model_name=', self.to_s
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_hash
|
23
|
-
attributes.merge kind: kind
|
24
|
-
end
|
25
|
-
|
26
|
-
def to_msgpack
|
27
|
-
to_hash.to_msgpack
|
28
|
-
end
|
29
|
-
|
30
|
-
def to_json(*args)
|
31
|
-
to_hash.to_json *args
|
32
|
-
end
|
33
|
-
|
34
|
-
def model
|
35
|
-
self.class
|
36
|
-
end
|
37
|
-
|
38
|
-
def full_error_messages
|
39
|
-
errors.full_messages.join '. '
|
40
|
-
end
|
41
|
-
|
42
|
-
module ClassMethods
|
43
|
-
|
44
|
-
def parse(*args, &block)
|
45
|
-
self.new *args, &block
|
46
|
-
end
|
47
|
-
|
48
|
-
def build(*args, &block)
|
49
|
-
self.new *args, &block
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'serf/message'
|
2
|
-
require 'serf/util/uuidable'
|
3
|
-
|
4
|
-
module Serf
|
5
|
-
module Messages
|
6
|
-
|
7
|
-
##
|
8
|
-
# An event message to signal that the serf code caught an
|
9
|
-
# exception during the processing of some message, which is
|
10
|
-
# represented by the context field.
|
11
|
-
#
|
12
|
-
# Instances of this class are norminally pushed to an
|
13
|
-
# error channel for out of band processing/notification.
|
14
|
-
#
|
15
|
-
class CaughtExceptionEvent
|
16
|
-
include Serf::Message
|
17
|
-
include Serf::Util::Uuidable
|
18
|
-
|
19
|
-
attr_accessor :context
|
20
|
-
attr_accessor :error
|
21
|
-
attr_accessor :message
|
22
|
-
attr_accessor :backtrace
|
23
|
-
|
24
|
-
def initialize(options={})
|
25
|
-
@context = options[:context]
|
26
|
-
@error = options[:error]
|
27
|
-
@message = options[:message]
|
28
|
-
@backtrace = options[:backtrace]
|
29
|
-
@uuid = options[:uuid]
|
30
|
-
end
|
31
|
-
|
32
|
-
def attributes
|
33
|
-
{
|
34
|
-
'context' => @context,
|
35
|
-
'error' => @error,
|
36
|
-
'message' => @message,
|
37
|
-
'backtrace' => @backtrace,
|
38
|
-
'uuid' => (@uuid || create_coded_uuid)
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
|
-
def to_s
|
43
|
-
to_hash.to_s
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'serf/message'
|
2
|
-
require 'serf/util/uuidable'
|
3
|
-
|
4
|
-
module Serf
|
5
|
-
module Messages
|
6
|
-
|
7
|
-
##
|
8
|
-
# This event signals that the serf process has accepted a message
|
9
|
-
# for processing at a later time. These events are normally sent
|
10
|
-
# in response to calling clients, which is a separate signal
|
11
|
-
# than any errors given.
|
12
|
-
#
|
13
|
-
class MessageAcceptedEvent
|
14
|
-
include Serf::Message
|
15
|
-
include Serf::Util::Uuidable
|
16
|
-
|
17
|
-
attr_accessor :message
|
18
|
-
|
19
|
-
def initialize(options={})
|
20
|
-
@message = options[:message]
|
21
|
-
@uuid = options[:uuid]
|
22
|
-
end
|
23
|
-
|
24
|
-
def attributes
|
25
|
-
{
|
26
|
-
'message' => @message,
|
27
|
-
'uuid' => (@uuid || create_coded_uuid)
|
28
|
-
}
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_s
|
32
|
-
to_hash.to_s
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'serf/util/uuidable'
|
2
|
-
|
3
|
-
module Serf
|
4
|
-
module More
|
5
|
-
|
6
|
-
##
|
7
|
-
# Assumes that Virtus has already been included in the class that
|
8
|
-
# also includes UuidFields.
|
9
|
-
#
|
10
|
-
module UuidFields
|
11
|
-
extend Serf::Util::Uuidable
|
12
|
-
|
13
|
-
def self.included(base)
|
14
|
-
base.attribute :uuid, String, default: lambda { |o,a| create_coded_uuid }
|
15
|
-
base.attribute :parent_uuid, String
|
16
|
-
base.attribute :origin_uuid, String
|
17
|
-
end
|
18
|
-
|
19
|
-
def create_child_uuids
|
20
|
-
{
|
21
|
-
uuid: UuidFields.create_coded_uuid,
|
22
|
-
parent_uuid: uuid,
|
23
|
-
origin_uuid: (origin_uuid || parent_uuid || uuid)
|
24
|
-
}
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|