asir 0.2.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/.gitignore +11 -0
- data/Gemfile +16 -0
- data/README.textile +50 -0
- data/Rakefile +83 -0
- data/VERSION +1 -0
- data/asir.gemspec +36 -0
- data/asir.riterate.yml +114 -0
- data/bin/asir +6 -0
- data/doc/Rakefile +8 -0
- data/doc/asir-sequence.pic +84 -0
- data/doc/asir-sequence.svg +1559 -0
- data/doc/sequence.pic +430 -0
- data/example/asir_control.sh +24 -0
- data/example/asir_control_client_http.rb +14 -0
- data/example/asir_control_client_zmq.rb +15 -0
- data/example/config/asir_config.rb +63 -0
- data/example/delayed_service.rb +15 -0
- data/example/ex01.rb +12 -0
- data/example/ex02.rb +12 -0
- data/example/ex03.rb +19 -0
- data/example/ex04.rb +33 -0
- data/example/ex05.rb +16 -0
- data/example/ex06.rb +26 -0
- data/example/ex07.rb +28 -0
- data/example/ex08.rb +30 -0
- data/example/ex09.rb +25 -0
- data/example/ex10.rb +24 -0
- data/example/ex11.rb +48 -0
- data/example/ex12.rb +34 -0
- data/example/ex13.rb +35 -0
- data/example/ex14.rb +30 -0
- data/example/ex15.rb +13 -0
- data/example/ex16.rb +33 -0
- data/example/ex17.rb +41 -0
- data/example/ex18.rb +62 -0
- data/example/ex19.rb +32 -0
- data/example/ex20.rb +28 -0
- data/example/ex21.rb +28 -0
- data/example/ex22.rb +15 -0
- data/example/ex23.rb +20 -0
- data/example/ex24.rb +35 -0
- data/example/example_helper.rb +51 -0
- data/example/sample_service.rb +162 -0
- data/example/unsafe_service.rb +12 -0
- data/hack_night/README.txt +18 -0
- data/hack_night/exercise/prob-1.rb +18 -0
- data/hack_night/exercise/prob-2.rb +21 -0
- data/hack_night/exercise/prob-3.rb +16 -0
- data/hack_night/exercise/prob-4.rb +36 -0
- data/hack_night/exercise/prob-5.rb +36 -0
- data/hack_night/exercise/prob-6.rb +95 -0
- data/hack_night/exercise/prob-7.rb +34 -0
- data/hack_night/solution/math_service.rb +11 -0
- data/hack_night/solution/prob-1.rb +12 -0
- data/hack_night/solution/prob-2.rb +15 -0
- data/hack_night/solution/prob-3.rb +17 -0
- data/hack_night/solution/prob-4.rb +37 -0
- data/hack_night/solution/prob-5.rb +21 -0
- data/hack_night/solution/prob-6.rb +33 -0
- data/hack_night/solution/prob-7.rb +36 -0
- data/lab/phony_proc.rb +31 -0
- data/lib/asir.rb +253 -0
- data/lib/asir/additional_data.rb +25 -0
- data/lib/asir/channel.rb +130 -0
- data/lib/asir/client.rb +111 -0
- data/lib/asir/code_block.rb +57 -0
- data/lib/asir/code_more.rb +50 -0
- data/lib/asir/coder.rb +26 -0
- data/lib/asir/coder/base64.rb +19 -0
- data/lib/asir/coder/chain.rb +30 -0
- data/lib/asir/coder/identity.rb +23 -0
- data/lib/asir/coder/json.rb +30 -0
- data/lib/asir/coder/marshal.rb +17 -0
- data/lib/asir/coder/null.rb +23 -0
- data/lib/asir/coder/proc.rb +22 -0
- data/lib/asir/coder/sign.rb +48 -0
- data/lib/asir/coder/xml.rb +213 -0
- data/lib/asir/coder/yaml.rb +33 -0
- data/lib/asir/coder/zlib.rb +21 -0
- data/lib/asir/configuration.rb +32 -0
- data/lib/asir/error.rb +34 -0
- data/lib/asir/identity.rb +36 -0
- data/lib/asir/initialization.rb +23 -0
- data/lib/asir/log.rb +82 -0
- data/lib/asir/main.rb +396 -0
- data/lib/asir/message.rb +31 -0
- data/lib/asir/message/delay.rb +35 -0
- data/lib/asir/object_resolving.rb +15 -0
- data/lib/asir/result.rb +39 -0
- data/lib/asir/retry_behavior.rb +54 -0
- data/lib/asir/transport.rb +241 -0
- data/lib/asir/transport/beanstalk.rb +217 -0
- data/lib/asir/transport/broadcast.rb +34 -0
- data/lib/asir/transport/buffer.rb +115 -0
- data/lib/asir/transport/composite.rb +19 -0
- data/lib/asir/transport/connection_oriented.rb +180 -0
- data/lib/asir/transport/delay.rb +38 -0
- data/lib/asir/transport/delegation.rb +53 -0
- data/lib/asir/transport/fallback.rb +36 -0
- data/lib/asir/transport/file.rb +88 -0
- data/lib/asir/transport/http.rb +54 -0
- data/lib/asir/transport/local.rb +21 -0
- data/lib/asir/transport/null.rb +14 -0
- data/lib/asir/transport/payload_io.rb +52 -0
- data/lib/asir/transport/rack.rb +73 -0
- data/lib/asir/transport/retry.rb +41 -0
- data/lib/asir/transport/stream.rb +35 -0
- data/lib/asir/transport/subprocess.rb +30 -0
- data/lib/asir/transport/tcp_socket.rb +34 -0
- data/lib/asir/transport/webrick.rb +50 -0
- data/lib/asir/transport/zmq.rb +110 -0
- data/lib/asir/uuid.rb +32 -0
- data/lib/asir/version.rb +3 -0
- data/spec/const_get_speed_spec.rb +33 -0
- data/spec/debug_helper.rb +20 -0
- data/spec/example_spec.rb +88 -0
- data/spec/json_spec.rb +128 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/xml_spec.rb +144 -0
- data/stylesheets/slides.css +105 -0
- metadata +173 -0
data/lib/asir/main.rb
ADDED
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
require 'asir'
|
|
2
|
+
require 'time'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
module ASIR
|
|
6
|
+
class Main
|
|
7
|
+
attr_accessor :verb, :adjective, :object, :identifier
|
|
8
|
+
attr_accessor :config_rb, :config
|
|
9
|
+
attr_accessor :log_dir, :pid_dir
|
|
10
|
+
attr_accessor :verbose
|
|
11
|
+
attr_accessor :exit_code
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
@verbose = 0
|
|
15
|
+
@progname = File.basename($0)
|
|
16
|
+
@log_dir = find_writable_directory :log_dir,
|
|
17
|
+
ENV['ASIR_LOG_DIR'],
|
|
18
|
+
'/var/log/asir',
|
|
19
|
+
'~/asir/log',
|
|
20
|
+
'/tmp'
|
|
21
|
+
@pid_dir = find_writable_directory :pid_dir,
|
|
22
|
+
ENV['ASIR_PID_DIR'],
|
|
23
|
+
'/var/run/asir',
|
|
24
|
+
'~/asir/run',
|
|
25
|
+
'/tmp'
|
|
26
|
+
@exit_code = 0
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find_writable_directory kind, *list
|
|
30
|
+
list.
|
|
31
|
+
reject { | p | ! p }.
|
|
32
|
+
map { | p | File.expand_path(p) }.
|
|
33
|
+
find { | p | File.writable?(p) } or
|
|
34
|
+
raise "Cannot find writable directory for #{kind}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def parse_args! args = ARGV.dup
|
|
38
|
+
@args = args
|
|
39
|
+
until args.empty?
|
|
40
|
+
case args.first
|
|
41
|
+
when /^([a-z0-9_]+=)(.*)/i
|
|
42
|
+
k, v = $1.to_sym, $2
|
|
43
|
+
args.shift
|
|
44
|
+
v = v.to_i if v == v.to_i.to_s
|
|
45
|
+
send(k, v)
|
|
46
|
+
else
|
|
47
|
+
break
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
@verb, @adjective, @object, @identifier = args.map{|x| x.to_sym}
|
|
51
|
+
@identifier ||= :'0'
|
|
52
|
+
self
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def log_str
|
|
56
|
+
"#{Time.now.gmtime.iso8601(4)} #{$$} #{log_str_no_time}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def log_str_no_time
|
|
60
|
+
"#{@progname} #{@verb} #{@adjective} #{@object} #{@identifier}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def run!
|
|
64
|
+
unless verb && adjective && object
|
|
65
|
+
@exit_code = 1
|
|
66
|
+
return usage!
|
|
67
|
+
end
|
|
68
|
+
config!(:config)
|
|
69
|
+
# $stderr.puts "log_file = #{log_file.inspect}"
|
|
70
|
+
case self.verb
|
|
71
|
+
when :restart
|
|
72
|
+
self.verb = :stop
|
|
73
|
+
_run_verb! && sleep(1)
|
|
74
|
+
self.verb = :start
|
|
75
|
+
_run_verb!
|
|
76
|
+
else
|
|
77
|
+
_run_verb!
|
|
78
|
+
end
|
|
79
|
+
self
|
|
80
|
+
rescue ::Exception => exc
|
|
81
|
+
$stderr.puts "#{log_str} ERROR\n#{exc.inspect}\n #{exc.backtrace * "\n "}"
|
|
82
|
+
@exit_code += 1
|
|
83
|
+
self
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def _run_verb!
|
|
87
|
+
sel = :"#{verb}_#{adjective}_#{object}!"
|
|
88
|
+
if @verbose >= 3
|
|
89
|
+
$stderr.puts "verb = #{verb.inspect}"
|
|
90
|
+
$stderr.puts "adjective = #{adjective.inspect}"
|
|
91
|
+
$stderr.puts "object = #{object.inspect}"
|
|
92
|
+
$stderr.puts "sel = #{sel.inspect}"
|
|
93
|
+
end
|
|
94
|
+
send(sel)
|
|
95
|
+
rescue ::Exception => exc
|
|
96
|
+
$stderr.puts "#{log_str} ERROR\n#{exc.inspect}\n #{exc.backtrace * "\n "}"
|
|
97
|
+
@exit_code += 1
|
|
98
|
+
raise
|
|
99
|
+
nil
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def method_missing sel, *args
|
|
103
|
+
log "method_missing #{sel}" if @verbose >= 3
|
|
104
|
+
case sel.to_s
|
|
105
|
+
when /^start_([^_]+)_worker!$/
|
|
106
|
+
_start_worker!
|
|
107
|
+
when /^status_([^_]+)_([^_]+)!$/
|
|
108
|
+
pid = server_pid
|
|
109
|
+
puts "#{log_str} pid #{pid}"
|
|
110
|
+
system("ps -fw -p #{pid}")
|
|
111
|
+
when /^log_([^_]+)_([^_]+)!$/
|
|
112
|
+
puts log_file
|
|
113
|
+
when /^taillog_([^_]+)_([^_]+)!$/
|
|
114
|
+
exec "tail -f #{log_file.inspect}"
|
|
115
|
+
when /^pid_([^_]+)_([^_]+)!$/
|
|
116
|
+
puts "#{pid_file} #{File.read(pid_file) rescue nil}"
|
|
117
|
+
when /^stop_([^_]+)_([^_]+)!$/
|
|
118
|
+
kill_server!
|
|
119
|
+
else
|
|
120
|
+
super
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def usage!
|
|
125
|
+
$stderr.puts <<"END"
|
|
126
|
+
SYNOPSIS:
|
|
127
|
+
asir [ <<options>> ... ] <<verb>> <<adjective>> <<object>> [ <<identifier>> ]
|
|
128
|
+
|
|
129
|
+
OPTIONS:
|
|
130
|
+
config_rb=file.rb ($ASIR_LOG_DIR)
|
|
131
|
+
pid_dir=dir/ ($ASIR_PID_DIR)
|
|
132
|
+
log_dir=dir/ ($ASIR_LOG_DIR)
|
|
133
|
+
verbose=[0-9]
|
|
134
|
+
|
|
135
|
+
VERBS:
|
|
136
|
+
start
|
|
137
|
+
stop
|
|
138
|
+
restart
|
|
139
|
+
status
|
|
140
|
+
log
|
|
141
|
+
pid
|
|
142
|
+
|
|
143
|
+
ADJECTIVE-OBJECTs:
|
|
144
|
+
beanstalk conduit
|
|
145
|
+
beanstalk worker
|
|
146
|
+
zmq worker
|
|
147
|
+
webrick worker
|
|
148
|
+
|
|
149
|
+
EXAMPLES:
|
|
150
|
+
|
|
151
|
+
export ASIR_CONFIG_RB="some_system/asir_config.rb"
|
|
152
|
+
asir start beanstalk conduit
|
|
153
|
+
asir status beanstalk conduit
|
|
154
|
+
|
|
155
|
+
asir start webrick worker
|
|
156
|
+
|
|
157
|
+
asir start beanstalk worker 1
|
|
158
|
+
asir start beanstalk worker 2
|
|
159
|
+
|
|
160
|
+
asir start zmq worker
|
|
161
|
+
asir start zmq worker 1
|
|
162
|
+
asir start zmq worker 2
|
|
163
|
+
END
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def start_beanstalk_conduit!
|
|
167
|
+
fork_server! "beanstalkd"
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def _start_worker! type = adjective
|
|
171
|
+
log "start_worker! #{type}"
|
|
172
|
+
type = type.to_s
|
|
173
|
+
fork_server! do
|
|
174
|
+
transport_file = "asir/transport/#{type}"
|
|
175
|
+
log "loading #{transport_file}"
|
|
176
|
+
require transport_file
|
|
177
|
+
_create_transport ASIR::Transport.const_get(type[0..0].upcase + type[1..-1])
|
|
178
|
+
_run_workers!
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
################################################################
|
|
183
|
+
|
|
184
|
+
def config_rb
|
|
185
|
+
@config_rb ||=
|
|
186
|
+
File.expand_path(ENV['ASIR_CONFIG_RB'] || 'config/asir_config.rb')
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def config_lambda
|
|
190
|
+
@config_lambda ||=
|
|
191
|
+
begin
|
|
192
|
+
file = config_rb
|
|
193
|
+
$stderr.puts "#{log_str} loading #{file} ..." if @verbose >= 1
|
|
194
|
+
expr = File.read(file)
|
|
195
|
+
expr = "begin; lambda do | asir |; #{expr}\n end; end"
|
|
196
|
+
cfg = Object.new.send(:eval, expr, binding, file, 1)
|
|
197
|
+
# cfg = load file
|
|
198
|
+
# $stderr.puts "#{log_str} loading #{file} DONE" if @verbose >= 1
|
|
199
|
+
raise "#{file} did not return a Proc, returned a #{cfg.class}" unless Proc === cfg
|
|
200
|
+
cfg
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def config! verb = @verb
|
|
205
|
+
(@config ||= { })[verb] ||=
|
|
206
|
+
begin
|
|
207
|
+
save_verb = @verb
|
|
208
|
+
@verb = verb
|
|
209
|
+
$stderr.puts "#{log_str} calling #{config_rb} asir.verb=#{@verb.inspect} ..." if @verbose >= 1
|
|
210
|
+
cfg = config_lambda.call(self)
|
|
211
|
+
$stderr.puts "#{log_str} calling #{config_rb} asir.verb=#{@verb.inspect} DONE" if @verbose >= 1
|
|
212
|
+
cfg
|
|
213
|
+
ensure
|
|
214
|
+
@verb = save_verb
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def pid_file
|
|
219
|
+
"#{pid_dir}/#{asir_basename}.pid"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def log_file
|
|
223
|
+
"#{log_dir}/#{asir_basename}.log"
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def asir_basename
|
|
227
|
+
"asir-#{adjective}-#{object}-#{identifier}"
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def fork_server! cmd = nil, &blk
|
|
231
|
+
pid = Process.fork do
|
|
232
|
+
run_server! cmd, &blk
|
|
233
|
+
end
|
|
234
|
+
log "forked pid #{pid}"
|
|
235
|
+
Process.detach(pid) # Forks a Thread? We are gonna exit anyway.
|
|
236
|
+
File.open(pid_file, "w+") { | o | o.puts pid }
|
|
237
|
+
File.chmod(0666, pid_file) rescue nil
|
|
238
|
+
|
|
239
|
+
# Wait and check if process still exists.
|
|
240
|
+
sleep 3
|
|
241
|
+
unless process_running? pid
|
|
242
|
+
raise "Server process #{pid} died to soon?"
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
self
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def run_server! cmd = nil
|
|
249
|
+
lf = File.open(log_file, "a+")
|
|
250
|
+
File.chmod(0666, log_file) rescue nil
|
|
251
|
+
$stdin.close rescue nil
|
|
252
|
+
STDIN.close rescue nil
|
|
253
|
+
STDOUT.reopen(lf)
|
|
254
|
+
$stdout.reopen(lf) if $stdout.object_id != STDOUT.object_id
|
|
255
|
+
STDERR.reopen(lf)
|
|
256
|
+
$stderr.reopen(lf) if $stderr.object_id != STDERR.object_id
|
|
257
|
+
# Process.daemon rescue nil # Ruby 1.9.x only.
|
|
258
|
+
lf.puts "#{log_str} starting pid #{$$}"
|
|
259
|
+
begin
|
|
260
|
+
if cmd
|
|
261
|
+
exec(cmd)
|
|
262
|
+
else
|
|
263
|
+
yield
|
|
264
|
+
end
|
|
265
|
+
ensure
|
|
266
|
+
lf.puts "#{log_str} finished pid #{$$}"
|
|
267
|
+
File.unlink(pid_file) rescue nil
|
|
268
|
+
end
|
|
269
|
+
self
|
|
270
|
+
rescue ::Exception => exc
|
|
271
|
+
msg = "ERROR pid #{$$}\n#{exc.inspect}\n #{exc.backtrace * "\n "}"
|
|
272
|
+
log msg, :stderr
|
|
273
|
+
raise
|
|
274
|
+
self
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def kill_server!
|
|
278
|
+
log "#{log_str} kill"
|
|
279
|
+
pid = server_pid
|
|
280
|
+
stop_pid! pid
|
|
281
|
+
rescue ::Exception => exc
|
|
282
|
+
log "#{log_str} ERROR\n#{exc.inspect}\n #{exc.backtrace * "\n "}", :stderr
|
|
283
|
+
raise
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def log msg, to_stderr = false
|
|
287
|
+
if to_stderr
|
|
288
|
+
$stderr.puts "#{log_str_no_time} #{msg}"
|
|
289
|
+
end
|
|
290
|
+
File.open(log_file, "a+") do | log |
|
|
291
|
+
log.puts "#{log_str} #{msg}"
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def server_pid
|
|
296
|
+
pid = File.read(pid_file).chomp!
|
|
297
|
+
pid.to_i
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def _create_transport default_class
|
|
301
|
+
config!(:environment)
|
|
302
|
+
case transport = config!(:transport)
|
|
303
|
+
when default_class
|
|
304
|
+
@transport = transport
|
|
305
|
+
else
|
|
306
|
+
raise "Expected config to return a #{default_class}, not a #{transport.class}"
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def worker_pids
|
|
311
|
+
(@worker_pids ||= { })[@adjective] ||= { }
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def _run_workers!
|
|
315
|
+
$0 = "#{@progname} #{@adjective} #{@object} #{@identifier}"
|
|
316
|
+
|
|
317
|
+
worker_id = 0
|
|
318
|
+
@transport.prepare_server!
|
|
319
|
+
worker_processes = @transport[:worker_processes] || 1
|
|
320
|
+
(worker_processes - 1).times do
|
|
321
|
+
wid = worker_id += 1
|
|
322
|
+
pid = Process.fork do
|
|
323
|
+
_run_transport_server! wid
|
|
324
|
+
end
|
|
325
|
+
Process.setgprp(pid, 0) rescue nil
|
|
326
|
+
worker_pids[wid] = pid
|
|
327
|
+
log "forked #{wid} pid #{pid}"
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
_run_transport_server!
|
|
331
|
+
ensure
|
|
332
|
+
log "worker 0 stopped"
|
|
333
|
+
_stop_workers!
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def _run_transport_server! wid = 0
|
|
337
|
+
log "running transport worker #{@transport.class} #{wid}"
|
|
338
|
+
config!(:start)
|
|
339
|
+
$0 += " #{wid} #{@transport.uri rescue nil}"
|
|
340
|
+
old_arg0 = $0.dup
|
|
341
|
+
after_receive_message = @transport.after_receive_message || lambda { | transport, message | nil }
|
|
342
|
+
@transport.after_receive_message = lambda do | transport, message |
|
|
343
|
+
$0 = "#{old_arg0} #{transport.message_count} #{message.identifier}"
|
|
344
|
+
after_receive_message.call(transport, message)
|
|
345
|
+
end
|
|
346
|
+
@transport.run_server!
|
|
347
|
+
self
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def _stop_workers!
|
|
351
|
+
workers = worker_pids.dup
|
|
352
|
+
worker_pids.clear
|
|
353
|
+
workers.each do | wid, pid |
|
|
354
|
+
config!(:stop)
|
|
355
|
+
stop_pid! pid, "wid #{wid} "
|
|
356
|
+
end
|
|
357
|
+
workers.each do | wid, pid |
|
|
358
|
+
wr = Process.waitpid(pid) rescue nil
|
|
359
|
+
log "stopped #{wid} pid #{pid} => #{wr.inspect}", :stderr
|
|
360
|
+
end
|
|
361
|
+
ensure
|
|
362
|
+
worker_pids.clear
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def stop_pid! pid, msg = nil
|
|
366
|
+
log "stopping #{msg}pid #{pid}", :stderr
|
|
367
|
+
if process_running? pid
|
|
368
|
+
log "TERM pid #{pid}"
|
|
369
|
+
Process.kill('TERM', pid) rescue nil
|
|
370
|
+
sleep 3
|
|
371
|
+
if @force or process_running? pid
|
|
372
|
+
log "KILL pid #{pid}", :stderr
|
|
373
|
+
Process.kill('KILL', pid) rescue nil
|
|
374
|
+
end
|
|
375
|
+
if process_running? pid
|
|
376
|
+
log "cant-stop pid #{pid}", :stderr
|
|
377
|
+
end
|
|
378
|
+
else
|
|
379
|
+
log "not-running? pid #{pid}", :stderr
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def process_running? pid
|
|
384
|
+
Process.kill(0, pid)
|
|
385
|
+
true
|
|
386
|
+
rescue ::Errno::ESRCH
|
|
387
|
+
false
|
|
388
|
+
rescue ::Exception => exc
|
|
389
|
+
$stderr.puts " DEBUG: process_running? #{pid} => #{exc.inspect}"
|
|
390
|
+
false
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
end # class
|
|
394
|
+
end # module
|
|
395
|
+
|
|
396
|
+
|
data/lib/asir/message.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
module ASIR
|
|
3
|
+
# !SLIDE
|
|
4
|
+
# Message
|
|
5
|
+
#
|
|
6
|
+
# Encapsulate the Ruby message from the Client to be handled by the Service.
|
|
7
|
+
class Message
|
|
8
|
+
include AdditionalData, Identity, CodeMore
|
|
9
|
+
attr_accessor :receiver, :receiver_class, :selector, :arguments, :block
|
|
10
|
+
attr_accessor :result, :one_way
|
|
11
|
+
|
|
12
|
+
def initialize r, s, a, b, p
|
|
13
|
+
@receiver, @selector, @arguments = r, s, a
|
|
14
|
+
@block = b if b
|
|
15
|
+
@receiver_class = @receiver.class
|
|
16
|
+
@one_way = p._one_way if p
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def invoke!
|
|
20
|
+
@result = Result.new(self, @receiver.__send__(@selector, *@arguments))
|
|
21
|
+
rescue *Error::Unforwardable.unforwardable => exc
|
|
22
|
+
@result = Result.new(self, nil, Error::Unforwardable.new(exc))
|
|
23
|
+
rescue ::Exception => exc
|
|
24
|
+
@result = Result.new(self, nil, exc)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Optional: Specifies the Numeric seconds or absolute Time to delay the Message until actual processing.
|
|
28
|
+
attr_accessor :delay
|
|
29
|
+
end
|
|
30
|
+
# !SLIDE END
|
|
31
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ASIR
|
|
2
|
+
class Message
|
|
3
|
+
module Delay
|
|
4
|
+
# Returns the number of seconds from now, that the message should be delayed.
|
|
5
|
+
# If message.delay is Numeric, sets message.delay to the Time to delay til.
|
|
6
|
+
# If message.delay is Time, returns (now - message.delay).to_f
|
|
7
|
+
# Returns Float if message.delay was set, or nil.
|
|
8
|
+
# Returns 0 if delay has already expired.
|
|
9
|
+
def relative_message_delay! message, now = nil
|
|
10
|
+
case delay = message.delay
|
|
11
|
+
when nil
|
|
12
|
+
when Numeric
|
|
13
|
+
now ||= Time.now
|
|
14
|
+
delay = delay.to_f
|
|
15
|
+
message.delay = (now + delay).utc
|
|
16
|
+
when Time
|
|
17
|
+
now ||= Time.now
|
|
18
|
+
delay = (delay - now).to_f
|
|
19
|
+
delay = 0 if delay < 0
|
|
20
|
+
else
|
|
21
|
+
raise TypeError, "Expected message.delay to be Numeric or Time, given #{delay.class}"
|
|
22
|
+
end
|
|
23
|
+
delay
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def wait_for_delay! message
|
|
27
|
+
while (delay = relative_message_delay!(message)) && delay > 0
|
|
28
|
+
sleep delay
|
|
29
|
+
end
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|