asir 1.1.12 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/ChangeLog +8 -1
- data/example/ex18.rb +3 -2
- data/example/ex26.rb +1 -1
- data/example/example_helper.rb +12 -2
- data/lib/asir.rb +1 -0
- data/lib/asir/additional_data.rb +4 -4
- data/lib/asir/client.rb +1 -2
- data/lib/asir/identity.rb +2 -18
- data/lib/asir/message/state.rb +18 -0
- data/lib/asir/transport.rb +53 -45
- data/lib/asir/transport/broadcast.rb +4 -5
- data/lib/asir/transport/buffer.rb +4 -4
- data/lib/asir/transport/composite.rb +1 -1
- data/lib/asir/transport/conduit.rb +8 -6
- data/lib/asir/transport/connection_oriented.rb +15 -12
- data/lib/asir/transport/database.rb +9 -11
- data/lib/asir/transport/delegation.rb +7 -12
- data/lib/asir/transport/demux.rb +2 -2
- data/lib/asir/transport/fallback.rb +4 -4
- data/lib/asir/transport/file.rb +6 -8
- data/lib/asir/transport/http.rb +11 -6
- data/lib/asir/transport/local.rb +8 -6
- data/lib/asir/transport/null.rb +1 -1
- data/lib/asir/transport/payload_io.rb +2 -2
- data/lib/asir/transport/rack.rb +7 -9
- data/lib/asir/transport/retry.rb +6 -5
- data/lib/asir/transport/subprocess.rb +5 -4
- data/lib/asir/transport/tcp_socket.rb +5 -5
- data/lib/asir/transport/thread.rb +12 -6
- data/lib/asir/transport/webrick.rb +9 -7
- data/lib/asir/uuid.rb +41 -3
- data/lib/asir/version.rb +1 -1
- data/spec/transport_spec.rb +8 -3
- data/spec/uuid_spec.rb +76 -0
- metadata +4 -1
data/.gitignore
CHANGED
data/ChangeLog
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
-
2012-12-
|
1
|
+
2012-12-29 Kurt A. Stephens <ks.github@kurtstephens.com>
|
2
|
+
|
3
|
+
* v1.2.0: New version: API changes.
|
4
|
+
* Message::State: internal object encapsulates state between #send_message, #receive_message, #send_result, #receive_result.
|
5
|
+
* Callbacks: most callbacks take a MessageResult object instead of Message and/or Result objects.
|
6
|
+
* UUID: Added new_uuid, process_uuid, counter_uuid, thread_uuid as mixin methods.
|
7
|
+
* Identity: Removed deprecated #client, #server attributes, use additional_data.
|
2
8
|
|
9
|
+
2012-12-28 Kurt A. Stephens <ks.github@kurtstephens.com>
|
3
10
|
* v1.1.12: New version.
|
4
11
|
* Rubinius: Rubinius -Xversion=18 and =19 support.
|
5
12
|
* XML: Really removed Coder::XML.
|
data/example/ex18.rb
CHANGED
@@ -9,8 +9,9 @@ begin
|
|
9
9
|
:encoder => ASIR::Coder::Yaml.new(:yaml_options => { :ASCII_8BIT_ok => true }))
|
10
10
|
tcp = ASIR::Transport::TcpSocket.new(:port => 31918,
|
11
11
|
:encoder => ASIR::Coder::Marshal.new)
|
12
|
-
start_server_proc = lambda do | transport,
|
13
|
-
|
12
|
+
start_server_proc = lambda do | transport, message_result |
|
13
|
+
message = message_result.message
|
14
|
+
# $stderr.puts "message = #{message.inspect}"
|
14
15
|
file.send_message(message)
|
15
16
|
server_process do
|
16
17
|
tcp.prepare_server!
|
data/example/ex26.rb
CHANGED
@@ -7,7 +7,7 @@ begin
|
|
7
7
|
Email.asir.transport = t =
|
8
8
|
ASIR::Transport::Thread.new
|
9
9
|
spawned_thread = nil
|
10
|
-
t.after_thread_new = lambda do | transport,
|
10
|
+
t.after_thread_new = lambda do | transport, message_result, thread |
|
11
11
|
spawned_thread = thread
|
12
12
|
$stderr.puts "\n #{$$}: Spawned Thread #{thread.inspect}"
|
13
13
|
end
|
data/example/example_helper.rb
CHANGED
@@ -48,7 +48,12 @@ def server_process &blk
|
|
48
48
|
if ENV['ASIR_JRUBY_SPAWNED']
|
49
49
|
$stderr.puts " spawned server at #{__FILE__}:#{__LINE__}"
|
50
50
|
puts "*** #{$$}: server process"; $stdout.flush
|
51
|
-
|
51
|
+
begin
|
52
|
+
yield
|
53
|
+
rescue ::Exception => exc
|
54
|
+
$stderr.puts "*** #{$$}: service ERROR: #{exc.inspect}\n #{exc.backtrace * " \n"}"
|
55
|
+
raise exc
|
56
|
+
end
|
52
57
|
Process.exit!(0)
|
53
58
|
# dont do client, client is our parent process.
|
54
59
|
else
|
@@ -64,7 +69,12 @@ def server_process &blk
|
|
64
69
|
# $stderr.puts " at #{__FILE__}:#{__LINE__}"
|
65
70
|
$server_pid = Process.fork do
|
66
71
|
puts "*** #{$$}: server process"; $stdout.flush
|
67
|
-
|
72
|
+
begin
|
73
|
+
yield
|
74
|
+
rescue ::Exception => exc
|
75
|
+
$stderr.puts "*** #{$$}: service ERROR: #{exc.inspect}\n #{exc.backtrace * " \n"}"
|
76
|
+
raise exc
|
77
|
+
end
|
68
78
|
end
|
69
79
|
end
|
70
80
|
sleep 1 # wait for server to be ready.
|
data/lib/asir.rb
CHANGED
data/lib/asir/additional_data.rb
CHANGED
@@ -28,19 +28,19 @@ module ASIR
|
|
28
28
|
|
29
29
|
module ModuleMethods
|
30
30
|
# Provide a getter method that delegates to addtional_data[...].
|
31
|
-
def
|
31
|
+
def addit_getter *names
|
32
32
|
names.each do | name |
|
33
33
|
name = name.to_sym
|
34
|
-
define_method(name) { | |
|
34
|
+
define_method(name) { | | self[name] }
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
# Provide getter and setter methods that delegate to addtional_data[...].
|
39
|
-
def
|
39
|
+
def addit_accessor *names
|
40
40
|
addr_getter *names
|
41
41
|
names.each do | name |
|
42
42
|
name = name.to_sym
|
43
|
-
define_method(:"#{name}=") { | v |
|
43
|
+
define_method(:"#{name}=") { | v | self[name] = v }
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
data/lib/asir/client.rb
CHANGED
@@ -54,8 +54,7 @@ module ASIR
|
|
54
54
|
message = Message.new(@receiver, selector, arguments, block, self)
|
55
55
|
message = @before_send_message.call(message) if @before_send_message
|
56
56
|
@__configure.call(message, self) if @__configure
|
57
|
-
|
58
|
-
result
|
57
|
+
transport.send_message(message) # => result
|
59
58
|
end
|
60
59
|
# Accept all other messages to be encoded and transported to a service.
|
61
60
|
alias :method_missing :send
|
data/lib/asir/identity.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'asir/uuid'
|
2
|
-
require 'thread' # Mutex
|
3
2
|
|
4
3
|
module ASIR
|
5
4
|
# !SLIDE
|
@@ -8,29 +7,14 @@ module ASIR
|
|
8
7
|
module Identity
|
9
8
|
attr_accessor :identifier, :timestamp
|
10
9
|
|
11
|
-
# Optional: Opaque data about the Client that created the Message.
|
12
|
-
attr_accessor :client
|
13
|
-
|
14
|
-
# Optional: Opaque data about the Service that handled the Result.
|
15
|
-
attr_accessor :server
|
16
|
-
|
17
10
|
# Creates a thread-safe unique identifier.
|
18
11
|
def create_identifier!
|
19
|
-
@identifier ||=
|
20
|
-
@@identifier_mutex.synchronize do
|
21
|
-
if @@uuid_pid != $$
|
22
|
-
@@uuid_pid = $$
|
23
|
-
@@uuid = nil
|
24
|
-
end
|
25
|
-
"#{@@counter += 1}-#{@@uuid ||= ::ASIR::UUID.generate}".freeze
|
26
|
-
end
|
12
|
+
@identifier ||= ::ASIR::UUID.counter_uuid
|
27
13
|
end
|
28
|
-
@@counter ||= 0; @@uuid ||= nil; @@uuid_pid = nil; @@identifier_mutex ||= Mutex.new
|
29
14
|
|
30
15
|
# Creates a timestamp.
|
31
16
|
def create_timestamp!
|
32
|
-
@timestamp ||=
|
33
|
-
::Time.now.gmtime
|
17
|
+
@timestamp ||= ::Time.now.gmtime
|
34
18
|
end
|
35
19
|
end
|
36
20
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ASIR
|
2
|
+
class Message
|
3
|
+
# !SLIDE
|
4
|
+
# Message::State
|
5
|
+
#
|
6
|
+
# Encapsulate the Message, Result and their payloads and other state.
|
7
|
+
# This is passed between Transport#send_request, #receive_request, #send_response, #receive_response.
|
8
|
+
class State
|
9
|
+
include Initialization
|
10
|
+
attr_accessor :message, :result
|
11
|
+
attr_accessor :message_payload, :result_payload
|
12
|
+
attr_accessor :message_opaque, :result_opaque
|
13
|
+
attr_accessor :in_stream, :out_stream
|
14
|
+
attr_accessor :additional_data
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/lib/asir/transport.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'time'
|
2
2
|
require 'asir/thread_variable'
|
3
3
|
require 'asir/message/delay'
|
4
|
+
require 'asir/message/state'
|
4
5
|
require 'asir/transport/conduit'
|
5
6
|
|
6
7
|
module ASIR
|
@@ -23,46 +24,44 @@ module ASIR
|
|
23
24
|
# * Send encoded Message.
|
24
25
|
# * Receive decoded Result.
|
25
26
|
def send_message message
|
26
|
-
@message_count ||= 0; @message_count += 1
|
27
|
+
@message_count ||= 0; @message_count += 1 # NOT THREAD-SAFE
|
27
28
|
message.create_timestamp! if needs_message_timestamp? message
|
28
29
|
message.create_identifier! if needs_message_identifier? message
|
29
|
-
@before_send_message.call(self, message) if @before_send_message
|
30
30
|
relative_message_delay! message
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
state = Message::State.new(:message => message, :message_payload => encoder.prepare.encode(message))
|
32
|
+
@before_send_message.call(self, state) if @before_send_message
|
33
|
+
_send_message(state)
|
34
|
+
receive_result(state)
|
34
35
|
end
|
35
36
|
|
36
37
|
# !SLIDE
|
37
38
|
# Transport#receive_message
|
38
39
|
# Receive Message payload from stream.
|
39
|
-
def receive_message
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
if @after_receive_message
|
47
|
-
@after_receive_message.call(self, message)
|
40
|
+
def receive_message state
|
41
|
+
@message_count ||= 0; @message_count += 1 # NOT THREAD-SAFE
|
42
|
+
if received = _receive_message(state)
|
43
|
+
if message = state.message = encoder.prepare.decode(state.message_payload)
|
44
|
+
message.additional_data!.update(state.additional_data) if state.additional_data
|
45
|
+
@after_receive_message.call(self, state) if @after_receive_message
|
46
|
+
self
|
48
47
|
end
|
49
48
|
end
|
50
|
-
req_and_state
|
51
49
|
end
|
52
50
|
# !SLIDE END
|
53
51
|
|
54
52
|
# !SLIDE
|
55
53
|
# Transport#send_result
|
56
54
|
# Send Result to stream.
|
57
|
-
def send_result
|
58
|
-
|
55
|
+
def send_result state
|
56
|
+
result = state.result
|
57
|
+
message = state.message
|
59
58
|
if @one_way && message.block
|
60
59
|
message.block.call(result)
|
61
60
|
else
|
62
|
-
#
|
61
|
+
# Avoid sending back entire Message in Result.
|
63
62
|
result.message = nil unless @coder_needs_result_message
|
64
|
-
result_payload = decoder.prepare.encode(result)
|
65
|
-
_send_result(
|
63
|
+
state.result_payload = decoder.prepare.encode(result)
|
64
|
+
_send_result(state)
|
66
65
|
end
|
67
66
|
end
|
68
67
|
attr_accessor :coder_needs_result_message
|
@@ -75,19 +74,24 @@ module ASIR
|
|
75
74
|
# * Receive Result payload
|
76
75
|
# * Decode Result.
|
77
76
|
# * Extract Result result or exception.
|
78
|
-
|
79
|
-
|
80
|
-
|
77
|
+
# * Invoke Exception or return Result value.
|
78
|
+
def receive_result state
|
79
|
+
value = nil
|
80
|
+
return value unless _receive_result(state)
|
81
|
+
result = state.result ||= decoder.prepare.decode(state.result_payload)
|
82
|
+
message = state.message
|
81
83
|
if result && ! message.one_way
|
84
|
+
result.message = message
|
82
85
|
if exc = result.exception
|
83
86
|
invoker.invoke!(exc, self)
|
84
87
|
else
|
85
88
|
if ! @one_way && message.block
|
86
89
|
message.block.call(result)
|
87
90
|
end
|
88
|
-
result.result
|
91
|
+
value = result.result
|
89
92
|
end
|
90
93
|
end
|
94
|
+
value
|
91
95
|
end
|
92
96
|
# !SLIDE END
|
93
97
|
|
@@ -118,8 +122,8 @@ module ASIR
|
|
118
122
|
# Proc to call with exception, if exception occurs within #serve_message!, but outside
|
119
123
|
# Message#invoke!.
|
120
124
|
#
|
121
|
-
# trans.on_exception.call(trans, exception, :message,
|
122
|
-
# trans.on_exception.call(trans, exception, :result,
|
125
|
+
# trans.on_exception.call(trans, exception, :message, message_state)
|
126
|
+
# trans.on_exception.call(trans, exception, :result, message_state)
|
123
127
|
attr_accessor :on_exception
|
124
128
|
|
125
129
|
attr_accessor :needs_message_identifier, :needs_message_timestamp
|
@@ -139,15 +143,15 @@ module ASIR
|
|
139
143
|
# !SLIDE
|
140
144
|
# Serve a Message.
|
141
145
|
def serve_message! in_stream, out_stream
|
142
|
-
|
146
|
+
state = message_ok = result = result_ok = nil
|
143
147
|
exception = original_exception = unforwardable_exception = nil
|
144
|
-
|
145
|
-
if
|
148
|
+
state = Message::State.new(:in_stream => in_stream, :out_stream => out_stream)
|
149
|
+
if receive_message(state)
|
146
150
|
message_ok = true
|
147
|
-
|
151
|
+
invoke_message!(state)
|
148
152
|
result_ok = true
|
149
153
|
if @after_invoke_message
|
150
|
-
@after_invoke_message.call(self,
|
154
|
+
@after_invoke_message.call(self, state)
|
151
155
|
end
|
152
156
|
self
|
153
157
|
else
|
@@ -156,7 +160,7 @@ module ASIR
|
|
156
160
|
rescue ::Exception => exc
|
157
161
|
exception = original_exception = exc
|
158
162
|
_log [ :message_error, exc ]
|
159
|
-
@on_exception.call(self, exc, :message,
|
163
|
+
@on_exception.call(self, exc, :message, state) if @on_exception
|
160
164
|
ensure
|
161
165
|
begin
|
162
166
|
if message_ok
|
@@ -165,15 +169,15 @@ module ASIR
|
|
165
169
|
when *Error::Unforwardable.unforwardable
|
166
170
|
unforwardable_exception = exception = Error::Unforwardable.new(exception)
|
167
171
|
end
|
168
|
-
result = Result.new(message, nil, exception)
|
172
|
+
state.result = Result.new(state.message, nil, exception)
|
169
173
|
end
|
170
174
|
if out_stream
|
171
|
-
send_result(
|
175
|
+
send_result(state)
|
172
176
|
end
|
173
177
|
end
|
174
178
|
rescue ::Exception => exc
|
175
|
-
_log [ :result_error, exc ]
|
176
|
-
@on_exception.call(self, exc, :result,
|
179
|
+
_log [ :result_error, exc, exc.backtrace ]
|
180
|
+
@on_exception.call(self, exc, :result, state) if @on_exception
|
177
181
|
end
|
178
182
|
raise original_exception if unforwardable_exception
|
179
183
|
end
|
@@ -227,21 +231,25 @@ module ASIR
|
|
227
231
|
end
|
228
232
|
|
229
233
|
# Invokes the Message object, returns a Result object.
|
230
|
-
def invoke_message!
|
231
|
-
result = nil
|
234
|
+
def invoke_message! state
|
232
235
|
Transport.with_attr! :current, self do
|
233
|
-
with_attr! :
|
234
|
-
|
235
|
-
|
236
|
+
with_attr! :message_state, state do
|
237
|
+
with_attr! :message, state.message do
|
238
|
+
wait_for_delay! state.message
|
239
|
+
state.result = invoker.invoke!(state.message, self)
|
236
240
|
# Hook for Exceptions.
|
237
|
-
if @on_result_exception && result.exception
|
238
|
-
@on_result_exception.call(self,
|
241
|
+
if @on_result_exception && state.result.exception
|
242
|
+
@on_result_exception.call(self, state)
|
239
243
|
end
|
240
244
|
end
|
241
245
|
end
|
242
|
-
|
246
|
+
end
|
247
|
+
self
|
243
248
|
end
|
244
|
-
|
249
|
+
|
250
|
+
# The current Message::State.
|
251
|
+
attr_accessor_thread :message_state
|
252
|
+
# The current Message being invoked. DEPRECATED.
|
245
253
|
attr_accessor_thread :message
|
246
254
|
|
247
255
|
# The current active Transport.
|
@@ -9,23 +9,22 @@ module ASIR
|
|
9
9
|
class Broadcast < self
|
10
10
|
include Composite
|
11
11
|
|
12
|
-
def _send_message
|
12
|
+
def _send_message state
|
13
13
|
result = first_exception = nil
|
14
14
|
transports.each do | transport |
|
15
15
|
begin
|
16
|
-
result = transport.send_message(message)
|
16
|
+
result = transport.send_message(state.message)
|
17
17
|
rescue ::Exception => exc
|
18
18
|
first_exception ||= exc
|
19
|
-
_handle_send_message_exception! transport,
|
19
|
+
_handle_send_message_exception! transport, state, exc
|
20
20
|
raise exc unless @continue_on_exception
|
21
21
|
end
|
22
22
|
end
|
23
23
|
if first_exception && @reraise_first_exception
|
24
24
|
raise first_exception
|
25
25
|
end
|
26
|
-
result
|
26
|
+
state.result = Result.new(state.message, result)
|
27
27
|
end
|
28
|
-
|
29
28
|
end
|
30
29
|
# !SLIDE END
|
31
30
|
end
|
@@ -25,15 +25,15 @@ module ASIR
|
|
25
25
|
|
26
26
|
# If paused, queue messages,
|
27
27
|
# Otherwise delegate immediately to #transport.
|
28
|
-
def _send_message
|
28
|
+
def _send_message state
|
29
29
|
return nil if @ignore
|
30
30
|
if paused?
|
31
31
|
@messages_mutex.synchronize do
|
32
|
-
@messages << message
|
32
|
+
@messages << state.message
|
33
33
|
end
|
34
34
|
nil
|
35
35
|
else
|
36
|
-
@transport.send_message(message)
|
36
|
+
@transport.send_message(state.message)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -97,7 +97,7 @@ module ASIR
|
|
97
97
|
# Usually used in worker Thread.
|
98
98
|
def process! non_block=false
|
99
99
|
@running = true
|
100
|
-
while @running && message = shift(non_block)
|
100
|
+
while @running && (message = shift(non_block))
|
101
101
|
@transport.send_message(message)
|
102
102
|
end
|
103
103
|
message
|
@@ -5,10 +5,11 @@ module Asir
|
|
5
5
|
# Conduit service support.
|
6
6
|
module Conduit
|
7
7
|
attr_accessor :conduit_options, :conduit_pid
|
8
|
+
|
8
9
|
def start_conduit! options = nil
|
9
|
-
opts =
|
10
|
+
opts = @conduit_options ||= {}
|
11
|
+
opts.update(:fork => true)
|
10
12
|
opts.update(options) if options
|
11
|
-
@conduit_options = opts
|
12
13
|
_log { "start_conduit! #{self}" } if @verbose >= 1
|
13
14
|
in_fork = opts[:fork]
|
14
15
|
raise "already running #{@conduit_pid} #{@conduit_cmd}" if @conduit_pid
|
@@ -19,7 +20,7 @@ module Asir
|
|
19
20
|
raise "Could not exec"
|
20
21
|
end
|
21
22
|
_log { "start_conduit! #{self} started pid=#{@conduit_pid.inspect}" } if @verbose >= 2
|
22
|
-
if pid_file = @conduit_options[:pid_file]
|
23
|
+
if pid_file = (@conduit_options || EMPTY_HASH)[:pid_file]
|
23
24
|
File.open(pid_file, "w") { | fh | fh.puts @conduit_pid }
|
24
25
|
end
|
25
26
|
else
|
@@ -29,7 +30,7 @@ module Asir
|
|
29
30
|
end
|
30
31
|
|
31
32
|
def conduit_pid
|
32
|
-
if ! @conduit_pid and pid_file = @conduit_options[:pid_file]
|
33
|
+
if ! @conduit_pid and pid_file = (@conduit_options || EMPTY_HASH)[:pid_file]
|
33
34
|
@conduit_pid = (File.read(pid_file).to_i rescue nil)
|
34
35
|
end
|
35
36
|
@conduit_pid
|
@@ -37,10 +38,11 @@ module Asir
|
|
37
38
|
|
38
39
|
def stop_conduit! opts = nil
|
39
40
|
if conduit_pid
|
40
|
-
pid_file = @conduit_options[:pid_file]
|
41
41
|
_log { "stop_conduit! #{self} pid=#{@conduit_pid.inspect}" } if @verbose >= 1
|
42
42
|
::Process.kill( (opts && opts[:signal]) || 'TERM', @conduit_pid)
|
43
|
-
|
43
|
+
if pid_file = (@conduit_options || EMPTY_HASH)[:pid_file]
|
44
|
+
::File.unlink(pid_file) rescue nil
|
45
|
+
end
|
44
46
|
::Process.waitpid @conduit_pid
|
45
47
|
end
|
46
48
|
self
|
@@ -52,33 +52,35 @@ module ASIR
|
|
52
52
|
|
53
53
|
# !SLIDE
|
54
54
|
# Sends the encoded Message payload String.
|
55
|
-
def _send_message
|
55
|
+
def _send_message state
|
56
56
|
stream.with_stream! do | io |
|
57
|
-
|
57
|
+
state.in_stream = io
|
58
|
+
_write(state.message_payload, io, state)
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
62
|
# !SLIDE
|
62
63
|
# Receives the encoded Message payload String.
|
63
|
-
def _receive_message
|
64
|
-
|
64
|
+
def _receive_message state
|
65
|
+
state.message_payload = _read(state.in_stream, state)
|
65
66
|
end
|
66
67
|
|
67
68
|
# !SLIDE
|
68
69
|
# Sends the encoded Result payload String.
|
69
|
-
def _send_result
|
70
|
-
unless @one_way || message.one_way
|
71
|
-
|
70
|
+
def _send_result state
|
71
|
+
unless @one_way || state.message.one_way
|
72
|
+
# $stderr.write "\n _send_result #{state.result_payload.inspect}\n\n"
|
73
|
+
_write(state.result_payload, state.out_stream, state)
|
74
|
+
true
|
72
75
|
end
|
73
76
|
end
|
74
77
|
|
75
78
|
# !SLIDE
|
76
79
|
# Receives the encoded Result payload String.
|
77
|
-
def _receive_result
|
78
|
-
unless @one_way || message.one_way
|
79
|
-
|
80
|
-
|
81
|
-
end
|
80
|
+
def _receive_result state
|
81
|
+
unless @one_way || state.message.one_way
|
82
|
+
state.result_payload = _read(state.in_stream, state)
|
83
|
+
true
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
@@ -115,6 +117,7 @@ module ASIR
|
|
115
117
|
end
|
116
118
|
|
117
119
|
def serve_connection!
|
120
|
+
_log { "serve_connection!: accepting connection" } if @verbose >= 2
|
118
121
|
in_stream, out_stream = _server_accept_connection! @server
|
119
122
|
_log { "serve_connection!: connected #{in_stream} #{out_stream}" } if @verbose >= 1
|
120
123
|
_server_serve_stream! in_stream, out_stream
|
@@ -19,29 +19,27 @@ module ASIR
|
|
19
19
|
self.needs_message_identifier = true
|
20
20
|
end
|
21
21
|
|
22
|
-
def _send_message
|
22
|
+
def _send_message state
|
23
23
|
if @before_message_save
|
24
|
-
@before_message_save.call(self,
|
24
|
+
@before_message_save.call(self, state)
|
25
25
|
end
|
26
|
-
message_payload.save!
|
26
|
+
state.message_payload.save!
|
27
27
|
# message[:database_id] ||= message_payload.database_id
|
28
28
|
if @after_message_save
|
29
|
-
@after_message_save.call(self,
|
29
|
+
@after_message_save.call(self, state)
|
30
30
|
end
|
31
|
-
nil # message_state
|
32
31
|
end
|
33
32
|
|
34
|
-
def _send_result
|
35
|
-
return if one_way? or message.one_way?
|
33
|
+
def _send_result state
|
34
|
+
return if one_way? or state.message.one_way?
|
36
35
|
if @before_result_save
|
37
|
-
@before_result_save.call(self,
|
36
|
+
@before_result_save.call(self, state)
|
38
37
|
end
|
39
|
-
result_payload.save!
|
38
|
+
state.result_payload.save!
|
40
39
|
result[:database_id] = result_payload.database_id
|
41
40
|
if @after_result_save
|
42
|
-
@after_result_save.call(self,
|
41
|
+
@after_result_save.call(self, state)
|
43
42
|
end
|
44
|
-
nil
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
@@ -14,14 +14,9 @@ module ASIR
|
|
14
14
|
# Proc to call(transport, message) when #send_message fails with no recourse.
|
15
15
|
attr_accessor :on_failed_message
|
16
16
|
|
17
|
-
# Return the subTransports
|
18
|
-
def _receive_result
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
# Return the subTransports#send_message result unmodified from #_send_message.
|
23
|
-
def receive_result message, opaque_result
|
24
|
-
opaque_result
|
17
|
+
# Return the subTransports' result unmodified from #_send_message.
|
18
|
+
def _receive_result state
|
19
|
+
true
|
25
20
|
end
|
26
21
|
|
27
22
|
def needs_message_identifier? message
|
@@ -40,10 +35,10 @@ module ASIR
|
|
40
35
|
end
|
41
36
|
|
42
37
|
# Called from within _send_message rescue.
|
43
|
-
def _handle_send_message_exception! transport,
|
44
|
-
_log { [ :send_message, :transport_failed, exc ] }
|
45
|
-
(message[:transport_exceptions] ||= [ ]) << "#{exc.inspect}: #{exc.backtrace.first}"
|
46
|
-
@on_send_message_exception.call(self,
|
38
|
+
def _handle_send_message_exception! transport, state, exc
|
39
|
+
_log { [ :send_message, :transport_failed, exc, exc.backtrace ] }
|
40
|
+
(state.message[:transport_exceptions] ||= [ ]) << "#{exc.inspect}: #{exc.backtrace.first}"
|
41
|
+
@on_send_message_exception.call(self, state, exc) if @on_send_message_exception
|
47
42
|
self
|
48
43
|
end
|
49
44
|
end
|
data/lib/asir/transport/demux.rb
CHANGED
@@ -7,16 +7,16 @@ module ASIR
|
|
7
7
|
class Fallback < self
|
8
8
|
include Composite
|
9
9
|
|
10
|
-
def _send_message
|
10
|
+
def _send_message state
|
11
11
|
result = sent = first_exception = nil
|
12
12
|
transports.each do | transport |
|
13
13
|
begin
|
14
|
-
result = transport.send_message(message)
|
14
|
+
result = transport.send_message(state.message)
|
15
15
|
sent = true
|
16
16
|
break
|
17
17
|
rescue ::Exception => exc
|
18
18
|
first_exception ||= exc
|
19
|
-
_handle_send_message_exception! transport,
|
19
|
+
_handle_send_message_exception! transport, state, exc
|
20
20
|
end
|
21
21
|
end
|
22
22
|
unless sent
|
@@ -25,7 +25,7 @@ module ASIR
|
|
25
25
|
end
|
26
26
|
raise FallbackError, "fallback failed"
|
27
27
|
end
|
28
|
-
result
|
28
|
+
state.result = Result.new(state.message, result)
|
29
29
|
end
|
30
30
|
class FallbackError < Error; end
|
31
31
|
end
|
data/lib/asir/transport/file.rb
CHANGED
@@ -15,24 +15,24 @@ module ASIR
|
|
15
15
|
def initialize opts = nil; @one_way = true; super; end
|
16
16
|
|
17
17
|
# Writes a Message payload String.
|
18
|
-
def _send_message
|
19
|
-
_write
|
18
|
+
def _send_message state
|
19
|
+
_write(state.message_payload, state.out_stream || stream, state)
|
20
20
|
ensure
|
21
21
|
close if file && ::File.pipe?(file)
|
22
22
|
end
|
23
23
|
|
24
24
|
# Returns a Message payload String.
|
25
|
-
def _receive_message
|
26
|
-
|
25
|
+
def _receive_message state
|
26
|
+
state.message_payload = _read(state.in_stream || stream, state)
|
27
27
|
end
|
28
28
|
|
29
29
|
# one-way; no Result.
|
30
|
-
def _send_result
|
30
|
+
def _send_result state
|
31
31
|
nil
|
32
32
|
end
|
33
33
|
|
34
34
|
# one-way; no Result.
|
35
|
-
def _receive_result
|
35
|
+
def _receive_result state
|
36
36
|
nil
|
37
37
|
end
|
38
38
|
|
@@ -63,7 +63,6 @@ module ASIR
|
|
63
63
|
# Named Pipe Server
|
64
64
|
|
65
65
|
def prepare_server!
|
66
|
-
# _log [ :prepare_pipe_server!, file ]
|
67
66
|
unless ::File.exist? file
|
68
67
|
system(cmd = "mkfifo #{file.inspect}") or raise "cannot run #{cmd.inspect}"
|
69
68
|
::File.chmod(perms, file) rescue nil if perms
|
@@ -72,7 +71,6 @@ module ASIR
|
|
72
71
|
alias :prepare_pipe_server! :prepare_server!
|
73
72
|
|
74
73
|
def run_server!
|
75
|
-
# _log [ :run_pipe_server!, file ]
|
76
74
|
with_server_signals! do
|
77
75
|
@running = true
|
78
76
|
while @running
|
data/lib/asir/transport/http.rb
CHANGED
@@ -30,18 +30,23 @@ module ASIR
|
|
30
30
|
|
31
31
|
# Send the Message payload String using HTTP POST.
|
32
32
|
# Returns the HTTPClient::Request response object.
|
33
|
-
def _send_message
|
33
|
+
def _send_message state
|
34
34
|
client.with_stream! do | client |
|
35
|
-
|
35
|
+
state.in_stream =
|
36
|
+
client.post(message_uri(state), state.message_payload)
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
40
|
+
# Subclasses can override.
|
41
|
+
def message_uri state
|
42
|
+
state.message[:uri] || uri
|
43
|
+
end
|
44
|
+
|
39
45
|
# Recieve the Result payload String from the opaque
|
40
46
|
# HTTPClient::Request response object returned from #_send_message.
|
41
|
-
def _receive_result
|
42
|
-
|
43
|
-
|
44
|
-
http_result_message.content.to_s
|
47
|
+
def _receive_result state
|
48
|
+
state.result_payload =
|
49
|
+
state.in_stream.content.to_s
|
45
50
|
end
|
46
51
|
|
47
52
|
CONTENT_TYPE = 'Content-Type'.freeze
|
data/lib/asir/transport/local.rb
CHANGED
@@ -6,14 +6,16 @@ module ASIR
|
|
6
6
|
# Send Message to same process.
|
7
7
|
# Requires Identity Coder.
|
8
8
|
class Local < self
|
9
|
-
#
|
10
|
-
def _send_message
|
11
|
-
invoke_message!(
|
9
|
+
# Capture Result object after invoking Message.
|
10
|
+
def _send_message state
|
11
|
+
invoke_message!(state)
|
12
|
+
self
|
12
13
|
end
|
13
14
|
|
14
|
-
#
|
15
|
-
def _receive_result
|
16
|
-
|
15
|
+
# Result object was captured in #_send_message.
|
16
|
+
def _receive_result state
|
17
|
+
state.result_payload = state.result
|
18
|
+
self
|
17
19
|
end
|
18
20
|
end
|
19
21
|
# !SLIDE END
|
data/lib/asir/transport/null.rb
CHANGED
@@ -14,7 +14,7 @@ module ASIR
|
|
14
14
|
HEADER = "# asir_payload_size: "
|
15
15
|
FOOTER = "\n# asir_payload_end"
|
16
16
|
|
17
|
-
def _write payload, stream,
|
17
|
+
def _write payload, stream, state
|
18
18
|
stream.write HEADER
|
19
19
|
stream.puts payload.size
|
20
20
|
stream.write payload
|
@@ -23,7 +23,7 @@ module ASIR
|
|
23
23
|
stream
|
24
24
|
end
|
25
25
|
|
26
|
-
def _read stream,
|
26
|
+
def _read stream, state
|
27
27
|
size = /\d+$/.match(stream.readline.chomp)[0].to_i # HEADER (size)
|
28
28
|
payload = stream.read(size)
|
29
29
|
stream.readline # FOOTER
|
data/lib/asir/transport/rack.rb
CHANGED
@@ -7,17 +7,16 @@ module ASIR
|
|
7
7
|
# Rack Transport
|
8
8
|
class Rack < HTTP
|
9
9
|
# Receive the Message payload String from the Rack::Request object.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
[ body, rack_req_res ]
|
10
|
+
def _receive_message state
|
11
|
+
rack_request = state.in_stream
|
12
|
+
state.message_payload = rack_request.body.read
|
14
13
|
end
|
15
14
|
|
16
15
|
# Send the Result payload String in the Rack::Response object as application/binary.
|
17
|
-
def _send_result
|
18
|
-
rack_response =
|
16
|
+
def _send_result state
|
17
|
+
rack_response = state.out_stream
|
19
18
|
rack_response[CONTENT_TYPE] = APPLICATION_BINARY
|
20
|
-
rack_response.write result_payload
|
19
|
+
rack_response.write state.result_payload
|
21
20
|
end
|
22
21
|
|
23
22
|
# Constructs a Rackable App from this Transport.
|
@@ -41,8 +40,7 @@ module ASIR
|
|
41
40
|
def call(env)
|
42
41
|
rq = ::Rack::Request.new(env)
|
43
42
|
rs = ::Rack::Response.new
|
44
|
-
|
45
|
-
serve_message! rack_rq_rs, rack_rq_rs
|
43
|
+
serve_message! rq, rs
|
46
44
|
rs.finish # => [ status, header, rbody ]
|
47
45
|
end
|
48
46
|
|
data/lib/asir/transport/retry.rb
CHANGED
@@ -13,19 +13,20 @@ module ASIR
|
|
13
13
|
# Proc to call(transport, message) before retry.
|
14
14
|
attr_accessor :before_retry
|
15
15
|
|
16
|
-
def _send_message
|
16
|
+
def _send_message state
|
17
17
|
first_exception = nil
|
18
18
|
with_retry do | action, data |
|
19
19
|
case action
|
20
20
|
when :try
|
21
|
-
transport.send_message(message)
|
21
|
+
result = transport.send_message(state.message)
|
22
|
+
state.result = Result.new(state.message, result)
|
22
23
|
when :rescue #, exc
|
23
24
|
first_exception ||= data
|
24
|
-
_handle_send_message_exception! transport,
|
25
|
+
_handle_send_message_exception! transport, state, data
|
25
26
|
when :retry #, exc
|
26
|
-
before_retry.call(self,
|
27
|
+
before_retry.call(self, state) if before_retry
|
27
28
|
when :failed
|
28
|
-
@on_failed_message.call(self,
|
29
|
+
@on_failed_message.call(self, state) if @on_failed_message
|
29
30
|
if first_exception && @reraise_first_exception
|
30
31
|
$! = first_exception
|
31
32
|
raise
|
@@ -11,18 +11,19 @@ module ASIR
|
|
11
11
|
@one_way = true; super
|
12
12
|
end
|
13
13
|
|
14
|
-
def _send_message
|
14
|
+
def _send_message state
|
15
15
|
Process.fork do
|
16
|
-
|
16
|
+
super
|
17
|
+
send_result(state)
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
20
21
|
# one-way; no Result
|
21
|
-
def _receive_result
|
22
|
+
def _receive_result state
|
22
23
|
end
|
23
24
|
|
24
25
|
# one-way; no Result
|
25
|
-
def _send_result
|
26
|
+
def _send_result state
|
26
27
|
end
|
27
28
|
end
|
28
29
|
# !SLIDE END
|
@@ -9,14 +9,14 @@ module ASIR
|
|
9
9
|
# !SLIDE
|
10
10
|
# TCP Socket Client
|
11
11
|
def _client_connect!
|
12
|
-
sock = TCPSocket.open(host, port)
|
12
|
+
sock = ::TCPSocket.open(host, port)
|
13
13
|
end
|
14
14
|
|
15
15
|
# !SLIDE
|
16
16
|
# TCP Socket Server
|
17
17
|
def _server!
|
18
|
-
@server = TCPServer.open(port)
|
19
|
-
@server.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, false)
|
18
|
+
@server = ::TCPServer.open(port)
|
19
|
+
@server.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, false)
|
20
20
|
end
|
21
21
|
|
22
22
|
def _server_accept_connection! server
|
@@ -24,8 +24,8 @@ module ASIR
|
|
24
24
|
[ socket, socket ] # Use same socket for in_stream and out_stream
|
25
25
|
end
|
26
26
|
|
27
|
-
def _server_close_connection!
|
28
|
-
|
27
|
+
def _server_close_connection! in_stream, out_stream
|
28
|
+
in_stream.close rescue nil
|
29
29
|
end
|
30
30
|
end
|
31
31
|
# !SLIDE END
|
@@ -12,7 +12,7 @@ module ASIR
|
|
12
12
|
# Defaults to ::Thread.
|
13
13
|
attr_accessor :thread_class
|
14
14
|
|
15
|
-
# Callback: call(self,
|
15
|
+
# Callback: call(self, MessageState, thr).
|
16
16
|
attr_accessor :after_thread_new
|
17
17
|
|
18
18
|
def initialize *args
|
@@ -20,20 +20,26 @@ module ASIR
|
|
20
20
|
@one_way = true; super
|
21
21
|
end
|
22
22
|
|
23
|
-
def _send_message
|
23
|
+
def _send_message state
|
24
24
|
thr = thread_class.new do
|
25
|
-
|
25
|
+
super
|
26
|
+
send_result(state)
|
26
27
|
end
|
27
|
-
|
28
|
+
state.in_stream = thr
|
29
|
+
@after_thread_new.call(self, state, thr) if @after_thread_new
|
28
30
|
thr
|
29
31
|
end
|
30
32
|
|
31
33
|
# one-way; no Result
|
32
|
-
def _receive_result
|
34
|
+
def _receive_result state
|
33
35
|
end
|
34
36
|
|
35
37
|
# one-way; no Result
|
36
|
-
def _send_result
|
38
|
+
def _send_result state
|
39
|
+
end
|
40
|
+
|
41
|
+
# one-may; no Result
|
42
|
+
def receive_result state
|
37
43
|
end
|
38
44
|
end
|
39
45
|
# !SLIDE END
|
@@ -9,16 +9,18 @@ module ASIR
|
|
9
9
|
|
10
10
|
# Server-side: WEBrick
|
11
11
|
|
12
|
-
# Receive the Message payload
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# Receive the Message payload from the HTTP Message body.
|
13
|
+
def _receive_message state
|
14
|
+
http_message = state.in_stream
|
15
|
+
state.message_payload = http_message.body
|
16
|
+
state.message_opaque = http_message
|
16
17
|
end
|
17
18
|
|
18
|
-
# Send the Result payload
|
19
|
-
def _send_result
|
19
|
+
# Send the Result payload in the HTTP Response body as application/binary.
|
20
|
+
def _send_result state
|
21
|
+
http_result = state.out_stream
|
20
22
|
http_result[CONTENT_TYPE] = APPLICATION_BINARY
|
21
|
-
http_result.body = result_payload
|
23
|
+
http_result.body = state.result_payload
|
22
24
|
end
|
23
25
|
|
24
26
|
def prepare_server! opts = { }
|
data/lib/asir/uuid.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
1
3
|
module ASIR
|
2
4
|
# Provides an RFC4122-compliant random (version 4) UUID service.
|
3
5
|
module UUID
|
@@ -13,19 +15,55 @@ module UUID
|
|
13
15
|
PROC_SYS_FILE = "/proc/sys/kernel/random/uuid".freeze
|
14
16
|
case
|
15
17
|
when File.exist?(PROC_SYS_FILE)
|
16
|
-
def
|
18
|
+
def new_uuid
|
17
19
|
File.read(PROC_SYS_FILE).chomp!
|
18
20
|
end
|
19
21
|
when (gem 'uuid' rescue nil)
|
20
22
|
require 'uuid'
|
21
|
-
def
|
23
|
+
def new_uuid
|
22
24
|
::UUID.generate
|
23
25
|
end
|
24
26
|
else
|
25
|
-
def
|
27
|
+
def new_uuid
|
26
28
|
raise "Unimplemented"
|
27
29
|
end
|
28
30
|
end
|
31
|
+
UUID_REGEX = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\Z/i
|
32
|
+
|
33
|
+
def process_uuid
|
34
|
+
@@process_uuid_mutex.synchronize do
|
35
|
+
if @@pid != $$
|
36
|
+
@@pid = $$
|
37
|
+
@@process_uuid = nil
|
38
|
+
end
|
39
|
+
@@process_uuid ||= new_uuid
|
40
|
+
end
|
41
|
+
end
|
42
|
+
@@pid = @@process_uuid = nil
|
43
|
+
@@process_uuid_mutex = Mutex.new
|
44
|
+
|
45
|
+
def counter_uuid
|
46
|
+
i = @@counter_mutex.synchronize do
|
47
|
+
@@counter += 1
|
48
|
+
end
|
49
|
+
"#{i}-#{process_uuid}"
|
50
|
+
end
|
51
|
+
@@counter ||= 0
|
52
|
+
@@counter_mutex = Mutex.new
|
53
|
+
COUNTER_UUID_REGEX = /\A[0-9]+-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\Z/i
|
54
|
+
|
55
|
+
# Returns a unique counter_uuid for a Thread.
|
56
|
+
# thr defaults to Thread.current.
|
57
|
+
def thread_uuid thr = nil
|
58
|
+
thr ||= Thread.current
|
59
|
+
thr[:'ASIR::UUID.thread_uuid'] || @@thread_uuid_mutex.synchronize do
|
60
|
+
thr[:'ASIR::UUID.thread_uuid'] = counter_uuid
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@@thread_uuid_mutex = Mutex.new
|
64
|
+
|
65
|
+
extend self
|
66
|
+
alias :generate :new_uuid # DEPRECATED
|
29
67
|
end
|
30
68
|
end
|
31
69
|
|
data/lib/asir/version.rb
CHANGED
data/spec/transport_spec.rb
CHANGED
@@ -40,10 +40,10 @@ describe "ASIR::Transport" do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should handle on_result_exception callbacks' do
|
43
|
-
_transport,
|
44
|
-
p = lambda do | transport,
|
43
|
+
_transport, _message_result = nil, nil
|
44
|
+
p = lambda do | transport, message_result |
|
45
45
|
_transport = transport
|
46
|
-
|
46
|
+
_message_result = message_result
|
47
47
|
end
|
48
48
|
transport.on_result_exception = p
|
49
49
|
|
@@ -71,12 +71,17 @@ describe "ASIR::Transport" do
|
|
71
71
|
|
72
72
|
_transport.should == object.transport
|
73
73
|
|
74
|
+
_result = _message_result.result
|
74
75
|
_result.class.should == ASIR::Result
|
75
76
|
_result.object_id.should == result.object_id
|
76
77
|
|
77
78
|
_result.message.class.should == ASIR::Message
|
78
79
|
_result.message.object_id.should == result.message.object_id
|
79
80
|
_result.exception.should == exc
|
81
|
+
|
82
|
+
_message = _message_result.message
|
83
|
+
_message.object_id.should == _message_result.message.object_id
|
84
|
+
|
80
85
|
end
|
81
86
|
end
|
82
87
|
|
data/spec/uuid_spec.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'asir/uuid'
|
2
|
+
|
3
|
+
describe "ASIR::UUID" do
|
4
|
+
attr_accessor :u
|
5
|
+
before { @u = ASIR::UUID }
|
6
|
+
|
7
|
+
it 'should return a UUID from #new_uuid.' do
|
8
|
+
x = u.new_uuid
|
9
|
+
x.should =~ ASIR::UUID::UUID_REGEX
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should return unique result from #new_uuid.' do
|
13
|
+
a = [ ]
|
14
|
+
10.times do
|
15
|
+
x = u.new_uuid
|
16
|
+
x.should =~ ASIR::UUID::UUID_REGEX
|
17
|
+
a << u.new_uuid
|
18
|
+
end
|
19
|
+
a.uniq.size.should == 10
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should single unique result per process from #process_uuid.' do
|
23
|
+
a = [ ]
|
24
|
+
10.times do
|
25
|
+
x = u.process_uuid
|
26
|
+
x.should =~ ASIR::UUID::UUID_REGEX
|
27
|
+
a << u.process_uuid
|
28
|
+
a << u.generate
|
29
|
+
end
|
30
|
+
a.uniq.size.should == 11
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should single unique result per process from #counter_uuid.' do
|
34
|
+
a = [ ]
|
35
|
+
10.times do
|
36
|
+
x = u.counter_uuid
|
37
|
+
x.should =~ ASIR::UUID::COUNTER_UUID_REGEX
|
38
|
+
a << x
|
39
|
+
a << u.process_uuid
|
40
|
+
a << u.generate
|
41
|
+
end
|
42
|
+
a.uniq.size.should == 21
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should single unique result per Thread from #thread_uuid.' do
|
46
|
+
a = [ ]
|
47
|
+
10.times do
|
48
|
+
x = u.thread_uuid
|
49
|
+
x.should =~ ASIR::UUID::COUNTER_UUID_REGEX
|
50
|
+
a << x
|
51
|
+
a << u.generate
|
52
|
+
a << u.process_uuid
|
53
|
+
end
|
54
|
+
a.uniq.size.should == 12
|
55
|
+
|
56
|
+
a = [ ]
|
57
|
+
b = [ ]
|
58
|
+
t1 = Thread.current
|
59
|
+
t2 = Thread.new do
|
60
|
+
10.times do
|
61
|
+
b << u.thread_uuid(t1)
|
62
|
+
b << u.thread_uuid(t2)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
10.times do
|
66
|
+
a << u.thread_uuid(t1)
|
67
|
+
a << u.thread_uuid(t2)
|
68
|
+
end
|
69
|
+
|
70
|
+
t2.join
|
71
|
+
c = a + b
|
72
|
+
c.uniq.size.should == 2
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asir
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -221,6 +221,7 @@ files:
|
|
221
221
|
- lib/asir/main.rb
|
222
222
|
- lib/asir/message.rb
|
223
223
|
- lib/asir/message/delay.rb
|
224
|
+
- lib/asir/message/state.rb
|
224
225
|
- lib/asir/object_resolving.rb
|
225
226
|
- lib/asir/poll_throttle.rb
|
226
227
|
- lib/asir/result.rb
|
@@ -264,6 +265,7 @@ files:
|
|
264
265
|
- spec/thread_pool_spec.rb
|
265
266
|
- spec/thread_variable_spec.rb
|
266
267
|
- spec/transport_spec.rb
|
268
|
+
- spec/uuid_spec.rb
|
267
269
|
- spec/yaml_spec.rb
|
268
270
|
- stylesheets/slides.css
|
269
271
|
homepage: http://github.com/kstephens/abstracting_services_in_ruby
|
@@ -303,4 +305,5 @@ test_files:
|
|
303
305
|
- spec/thread_pool_spec.rb
|
304
306
|
- spec/thread_variable_spec.rb
|
305
307
|
- spec/transport_spec.rb
|
308
|
+
- spec/uuid_spec.rb
|
306
309
|
- spec/yaml_spec.rb
|