asir 0.2.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -2
- data/README.textile +4 -2
- data/VERSION +1 -1
- data/asir.gemspec +1 -4
- data/asir.riterate.yml +1 -0
- data/bin/asir +2 -1
- data/example/asir_control.sh +63 -1
- data/example/asir_control_client_http.rb +2 -2
- data/example/asir_control_client_resque.rb +16 -0
- data/example/asir_control_client_zmq.rb +3 -3
- data/example/config/asir_config.rb +20 -8
- data/example/ex02.rb +1 -1
- data/example/ex03.rb +2 -2
- data/example/ex04.rb +2 -2
- data/example/ex05.rb +1 -1
- data/example/ex06.rb +6 -5
- data/example/ex07.rb +2 -2
- data/example/ex08.rb +2 -2
- data/example/ex09.rb +2 -2
- data/example/ex10.rb +2 -2
- data/example/ex11.rb +5 -5
- data/example/ex12.rb +6 -6
- data/example/ex13.rb +4 -4
- data/example/ex14.rb +4 -4
- data/example/ex15.rb +2 -2
- data/example/ex16.rb +8 -8
- data/example/ex17.rb +12 -11
- data/example/ex18.rb +5 -5
- data/example/ex19.rb +3 -3
- data/example/ex20.rb +3 -3
- data/example/ex21.rb +3 -3
- data/example/ex22.rb +1 -1
- data/example/ex23.rb +2 -2
- data/example/ex24.rb +4 -4
- data/example/ex25.rb +41 -0
- data/example/example_helper.rb +38 -3
- data/example/sample_service.rb +4 -4
- data/hack_night/exercise/prob-3.rb +3 -3
- data/hack_night/exercise/prob-6.rb +2 -2
- data/hack_night/exercise/prob-7.rb +2 -2
- data/hack_night/solution/prob-2.rb +2 -2
- data/hack_night/solution/prob-3.rb +3 -3
- data/hack_night/solution/prob-6.rb +7 -6
- data/hack_night/solution/prob-7.rb +6 -6
- data/{spec → lab}/const_get_speed_spec.rb +0 -0
- data/lib/asir.rb +29 -7
- data/lib/asir/additional_data.rb +25 -0
- data/lib/asir/channel.rb +4 -5
- data/lib/asir/client.rb +29 -13
- data/lib/asir/config.rb +8 -0
- data/lib/asir/description.rb +34 -0
- data/lib/asir/environment.rb +96 -0
- data/lib/asir/error.rb +4 -1
- data/lib/asir/invoker.rb +14 -0
- data/lib/asir/main.rb +84 -103
- data/lib/asir/message.rb +1 -1
- data/lib/asir/poll_throttle.rb +53 -0
- data/lib/asir/retry_behavior.rb +1 -1
- data/lib/asir/thread_variable.rb +183 -0
- data/lib/asir/transport.rb +36 -23
- data/lib/asir/transport/beanstalk.rb +18 -52
- data/lib/asir/transport/conduit.rb +42 -0
- data/lib/asir/transport/connection_oriented.rb +32 -56
- data/lib/asir/transport/delegation.rb +5 -5
- data/lib/asir/transport/demux.rb +33 -0
- data/lib/asir/transport/file.rb +5 -3
- data/lib/asir/transport/payload_io.rb +8 -4
- data/lib/asir/transport/resque.rb +212 -0
- data/lib/asir/transport/stream.rb +19 -9
- data/lib/asir/transport/tcp_socket.rb +3 -2
- data/lib/asir/transport/zmq.rb +14 -17
- data/lib/asir/uri_config.rb +51 -0
- data/lib/asir/version.rb +1 -1
- data/spec/client_spec.rb +48 -0
- data/spec/demux_spec.rb +38 -0
- data/spec/json_spec.rb +0 -2
- data/spec/message_spec.rb +68 -0
- data/spec/performance_spec.rb +66 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/thread_variable_spec.rb +135 -0
- data/spec/transport_spec.rb +82 -0
- metadata +28 -4
@@ -81,9 +81,9 @@ begin
|
|
81
81
|
|
82
82
|
# system("curl http://localhost:#{port}/")
|
83
83
|
|
84
|
-
MathService.
|
84
|
+
MathService.asir.transport = t
|
85
85
|
|
86
|
-
MathService.
|
86
|
+
MathService.asir.sum([1, 2, 3])
|
87
87
|
|
88
88
|
rescue Exception => err
|
89
89
|
$stderr.puts "ERROR: #{err.inspect}\n#{err.backtrace * "\n"}"
|
@@ -21,8 +21,8 @@ begin
|
|
21
21
|
end
|
22
22
|
sleep 1 # wait for server to start
|
23
23
|
|
24
|
-
MathService.
|
25
|
-
MathService.
|
24
|
+
MathService.asir.transport = t
|
25
|
+
MathService.asir.sum([1, 2, 3])
|
26
26
|
|
27
27
|
rescue Exception => err
|
28
28
|
$stderr.puts "ERROR: #{err.inspect}\n#{err.backtrace * "\n"}"
|
@@ -11,7 +11,7 @@ MathService.send(:include, ASIR::Client)
|
|
11
11
|
# Driver:
|
12
12
|
|
13
13
|
begin
|
14
|
-
MathService.
|
15
|
-
MathService.
|
16
|
-
puts MathService.
|
14
|
+
MathService.asir.transport = ASIR::Transport::Subprocess.new
|
15
|
+
MathService.asir.transport._log_enabled = true
|
16
|
+
puts MathService.asir.sum([1, 2, 3])
|
17
17
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
# Write a ASIR::Transport::HTTP class that uses HTTP::Client for transport send_result and receive_result.
|
2
|
+
# And WEBrick to handle requests.
|
2
3
|
|
3
4
|
$: << File.expand_path("../../../lib", __FILE__)
|
4
|
-
require 'asir/transport/
|
5
|
+
require 'asir/transport/webrick'
|
5
6
|
require 'asir/coder/marshal'
|
6
7
|
|
7
8
|
require 'math_service'
|
@@ -9,19 +10,19 @@ MathService.send(:include, ASIR::Client)
|
|
9
10
|
|
10
11
|
port = 3001
|
11
12
|
begin
|
12
|
-
t = ASIR::Transport::
|
13
|
+
t = ASIR::Transport::Webrick.new(:uri => "http://localhost:#{port}/")
|
13
14
|
t._log_enabled = true
|
14
15
|
c = t.encoder = ASIR::Coder::Marshal.new
|
15
16
|
c._log_enabled = true
|
16
17
|
|
17
18
|
server_pid = Process.fork do
|
18
|
-
t.
|
19
|
-
t.
|
19
|
+
t.prepare_server!
|
20
|
+
t.run_server!
|
20
21
|
end
|
21
22
|
sleep 1 # wait for server to start
|
22
23
|
|
23
|
-
MathService.
|
24
|
-
MathService.
|
24
|
+
MathService.asir.transport = t
|
25
|
+
MathService.asir.sum([1, 2, 3])
|
25
26
|
|
26
27
|
rescue Exception => err
|
27
28
|
$stderr.puts "ERROR: #{err.inspect}\n#{err.backtrace * "\n"}"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Use the Marshal and Base64 coders in prob-4.rb
|
2
2
|
|
3
3
|
$: << File.expand_path("../../../lib", __FILE__)
|
4
|
-
require 'asir/transport/
|
4
|
+
require 'asir/transport/webrick'
|
5
5
|
require 'asir/coder/marshal'
|
6
6
|
require 'asir/coder/base64'
|
7
7
|
require 'asir/coder/chain'
|
@@ -11,7 +11,7 @@ MathService.send(:include, ASIR::Client)
|
|
11
11
|
|
12
12
|
port = 3001
|
13
13
|
begin
|
14
|
-
t = ASIR::Transport::
|
14
|
+
t = ASIR::Transport::Webrick.new(:uri => "http://localhost:#{port}/")
|
15
15
|
t._log_enabled = true
|
16
16
|
c = t.encoder = ASIR::Coder::Chain.new(:encoders =>
|
17
17
|
[
|
@@ -21,13 +21,13 @@ begin
|
|
21
21
|
c._log_enabled = true
|
22
22
|
|
23
23
|
server_pid = Process.fork do
|
24
|
-
t.
|
25
|
-
t.
|
24
|
+
t.prepare_server!
|
25
|
+
t.run_server!
|
26
26
|
end
|
27
27
|
sleep 1 # wait for server to start
|
28
28
|
|
29
|
-
MathService.
|
30
|
-
MathService.
|
29
|
+
MathService.asir.transport = t
|
30
|
+
MathService.asir.sum([1, 2, 3])
|
31
31
|
rescue Exception => err
|
32
32
|
$stderr.puts "ERROR: #{err.inspect}\n#{err.backtrace * "\n"}"
|
33
33
|
ensure
|
File without changes
|
data/lib/asir.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# * Kurt Stephens
|
5
5
|
# * Enova Financial
|
6
|
-
# * 2012/
|
6
|
+
# * 2012/07/18
|
7
7
|
# * Slides -- "":http://kurtstephens.com/pub/ruby/abstracting_services_in_ruby/asir.slides/
|
8
8
|
# * Code -- "":http://kurtstephens.com/pub/ruby/abstracting_services_in_ruby/
|
9
9
|
# * Git -- "":http://github.com/kstephens/abstracting_services_in_ruby
|
@@ -34,7 +34,7 @@
|
|
34
34
|
# * Directionality: One-way, Two-way
|
35
35
|
# * Synchronicity: Synchronous, Asynchronous, Delayed, Buffered
|
36
36
|
# * Distribution: Local Thread, Local Process, Distributed
|
37
|
-
# * Transport: File, IPC, Pipe, Network
|
37
|
+
# * Transport: File, IPC, Pipe, Network, Beanstalk, ZMQ, Resque
|
38
38
|
# * Robustness: Retry, Replay, Fallback
|
39
39
|
# * Encoding: XML, JSON, YAML, Base64, Compression
|
40
40
|
#
|
@@ -73,11 +73,11 @@
|
|
73
73
|
# !SLIDE
|
74
74
|
# Messaging
|
75
75
|
#
|
76
|
-
# * "
|
76
|
+
# * "Send a Message", "Call a Function" are all the same, in *all* languages.
|
77
77
|
# ** Decomposed into lookup() and apply().
|
78
|
-
# * "Send Message", not "Call a Method".
|
78
|
+
# * "Send a Message", not "Call a Method".
|
79
79
|
# * Messaging abstracts:
|
80
|
-
# **
|
80
|
+
# ** Behavior from Implementation.
|
81
81
|
# ** Transfer of control (method, function invocation, RPC, etc).
|
82
82
|
|
83
83
|
# !SLIDE
|
@@ -111,8 +111,8 @@
|
|
111
111
|
# * Proxy
|
112
112
|
# * Message -> Just a Ruby message.
|
113
113
|
# * Result, Exception (two-way) -> Return value or else.
|
114
|
-
# * Transport -> (file, pipe, http, queue,
|
115
|
-
# * Encoder, Decoder -> Coder (Marshal, XML, JSON,
|
114
|
+
# * Transport -> (file, pipe, http, queue, socket, ZMQ).
|
115
|
+
# * Encoder, Decoder -> Coder (Marshal, XML, JSON, zlib).
|
116
116
|
#
|
117
117
|
# !SLIDE END
|
118
118
|
|
@@ -127,6 +127,25 @@
|
|
127
127
|
#
|
128
128
|
# !SLIDE END
|
129
129
|
|
130
|
+
# !SLIDE
|
131
|
+
# Abstraction Leads to Rich Features
|
132
|
+
#
|
133
|
+
# * One-way and two-way requests as Module or instance methods.
|
134
|
+
# * Message support:
|
135
|
+
# ** Delayed Messages.
|
136
|
+
# * Transports:
|
137
|
+
# ** Null, Local, File, Named Pipe, TCP.
|
138
|
+
# ** HTTP under WEBrick or as Rack application.
|
139
|
+
# ** Beanstalkd, ZeroMQ, Resque.
|
140
|
+
# ** Buffered, Broadcast, Fallback, Demux transports.
|
141
|
+
# ** Time-decaying retry logic.
|
142
|
+
# * Encodings:
|
143
|
+
# ** Marshal, XML, JSON, YAML, Base64, ZLib.
|
144
|
+
# ** Chained encodings.
|
145
|
+
# ** Signed payloads.
|
146
|
+
#
|
147
|
+
# !SLIDE END
|
148
|
+
|
130
149
|
# !SLIDE
|
131
150
|
# Simple
|
132
151
|
#
|
@@ -211,11 +230,13 @@ end
|
|
211
230
|
Asir = ASIR
|
212
231
|
|
213
232
|
require "asir/version"
|
233
|
+
require 'asir/config'
|
214
234
|
require 'asir/error'
|
215
235
|
require 'asir/log'
|
216
236
|
require 'asir/initialization'
|
217
237
|
require 'asir/additional_data'
|
218
238
|
require 'asir/object_resolving'
|
239
|
+
require 'asir/thread_variable'
|
219
240
|
require 'asir/identity'
|
220
241
|
require 'asir/code_block'
|
221
242
|
require 'asir/code_more'
|
@@ -226,6 +247,7 @@ require 'asir/coder'
|
|
226
247
|
require 'asir/coder/null'
|
227
248
|
require 'asir/coder/identity'
|
228
249
|
require 'asir/transport'
|
250
|
+
require 'asir/invoker'
|
229
251
|
require 'asir/channel'
|
230
252
|
require 'asir/transport/local'
|
231
253
|
|
data/lib/asir/additional_data.rb
CHANGED
@@ -19,6 +19,31 @@ module ASIR
|
|
19
19
|
def []= key, value
|
20
20
|
(@additional_data ||= { })[key] = value
|
21
21
|
end
|
22
|
+
|
23
|
+
def self.included target
|
24
|
+
super
|
25
|
+
target.extend(ModuleMethods)
|
26
|
+
end
|
27
|
+
|
28
|
+
module ModuleMethods
|
29
|
+
# Provide a getter method that delegates to addtional_data[...].
|
30
|
+
def addr_getter *names
|
31
|
+
names.each do | name |
|
32
|
+
name = name.to_sym
|
33
|
+
define_method(name) { | | addtional_data[name] }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Provide getter and setter methods that delegate to addtional_data[...].
|
38
|
+
def addr_accessor *names
|
39
|
+
addr_getter *names
|
40
|
+
names.each do | name |
|
41
|
+
name = name.to_sym
|
42
|
+
define_method(:"#{name}=") { | v | addtional_data[name] = v }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
22
47
|
end
|
23
48
|
# !SLIDE END
|
24
49
|
end
|
data/lib/asir/channel.rb
CHANGED
@@ -10,11 +10,11 @@ module ASIR
|
|
10
10
|
attr_accessor :on_connect, :on_close, :on_retry, :on_error
|
11
11
|
|
12
12
|
ON_ERROR = lambda do | channel, exc, action, stream |
|
13
|
-
channel.close rescue nil
|
13
|
+
channel.close rescue nil
|
14
14
|
raise exc
|
15
15
|
end
|
16
16
|
ON_CLOSE = lambda do | channel, stream |
|
17
|
-
stream.close
|
17
|
+
stream.close rescue nil if stream
|
18
18
|
end
|
19
19
|
ON_RETRY = lambda do | channel, exc, action |
|
20
20
|
end
|
@@ -101,9 +101,8 @@ module ASIR
|
|
101
101
|
# Maps from Channel objects to actual stream.
|
102
102
|
def _streams
|
103
103
|
streams = Thread.current[:'ASIR::Channel._streams'] ||= { }
|
104
|
-
if
|
105
|
-
@owning_process
|
106
|
-
@owning_process > $$ # PIDs wrapped around?
|
104
|
+
if @owning_process != $$ || # child process?
|
105
|
+
@owning_process > $$ # PIDs wrapped around?
|
107
106
|
@owning_process = $$
|
108
107
|
streams.clear
|
109
108
|
end
|
data/lib/asir/client.rb
CHANGED
@@ -13,27 +13,32 @@ module ASIR
|
|
13
13
|
end
|
14
14
|
|
15
15
|
module CommonMethods
|
16
|
-
def
|
17
|
-
|
16
|
+
def asir_options &blk
|
17
|
+
asir._configure(&blk)
|
18
18
|
end
|
19
|
+
alias_method :"#{ASIR::Config.client_method}_options", :asir_options if ASIR::Config.client_method
|
19
20
|
end
|
20
21
|
|
21
22
|
module ModuleMethods
|
22
23
|
include CommonMethods
|
23
24
|
# Proxies are cached for Module/Class methods because serialization will not include
|
24
25
|
# Transport.
|
25
|
-
def
|
26
|
-
@
|
26
|
+
def asir
|
27
|
+
@_asir ||= ASIR::Client::Proxy.new(self, self)
|
27
28
|
end
|
29
|
+
alias_method ASIR::Config.client_method, :asir if ASIR::Config.client_method
|
28
30
|
end
|
29
31
|
|
30
32
|
module InstanceMethods
|
31
33
|
include CommonMethods
|
32
34
|
# Proxies are not cached in instances because receiver is to be serialized by
|
33
35
|
# its Transport's Coder.
|
34
|
-
def
|
35
|
-
|
36
|
+
def asir
|
37
|
+
proxy = self.class.asir.dup
|
38
|
+
proxy.receiver = self
|
39
|
+
proxy
|
36
40
|
end
|
41
|
+
alias_method ASIR::Config.client_method, :asir if ASIR::Config.client_method
|
37
42
|
end
|
38
43
|
|
39
44
|
# !SLIDE
|
@@ -41,14 +46,14 @@ module ASIR
|
|
41
46
|
#
|
42
47
|
# Provide client interface proxy to a service.
|
43
48
|
class Proxy
|
44
|
-
attr_accessor :receiver
|
49
|
+
attr_accessor :receiver, :receiver_class
|
45
50
|
|
46
51
|
# Accept messages as a proxy for the receiver.
|
47
52
|
# Blocks are used represent a "continuation" for the Result.
|
48
53
|
def send selector, *arguments, &block
|
49
54
|
message = Message.new(@receiver, selector, arguments, block, self)
|
50
55
|
message = @before_send_message.call(message) if @before_send_message
|
51
|
-
@__configure.call(message) if @__configure
|
56
|
+
@__configure.call(message, self) if @__configure
|
52
57
|
result = transport.send_message(message)
|
53
58
|
result
|
54
59
|
end
|
@@ -80,8 +85,12 @@ module ASIR
|
|
80
85
|
# Returns a new Client Proxy with a block to be called with the Message.
|
81
86
|
# This block can configure additional options of the Message before
|
82
87
|
# it is sent to the Transport.
|
88
|
+
#
|
89
|
+
# Call sequence:
|
90
|
+
#
|
91
|
+
# proxy.__configure.call(message, proxy).
|
83
92
|
def _configure &blk
|
84
|
-
proxy = self.dup
|
93
|
+
proxy = @receiver == @receiver_class ? self.dup : self
|
85
94
|
proxy.__configure = blk
|
86
95
|
proxy
|
87
96
|
end
|
@@ -90,12 +99,19 @@ module ASIR
|
|
90
99
|
# !SLIDE
|
91
100
|
# Configuration Callbacks
|
92
101
|
|
93
|
-
def initialize rcvr
|
94
|
-
|
95
|
-
|
96
|
-
|
102
|
+
def initialize rcvr, rcvr_class
|
103
|
+
@receiver = rcvr
|
104
|
+
@receiver_class = rcvr_class
|
105
|
+
_configure!
|
106
|
+
end
|
107
|
+
|
108
|
+
def _configure!
|
109
|
+
key = @receiver_class
|
110
|
+
(@@config_callbacks[key] ||
|
111
|
+
@@config_callbacks[key.name] ||
|
97
112
|
@@config_callbacks[nil] ||
|
98
113
|
IDENTITY_LAMBDA).call(self)
|
114
|
+
self
|
99
115
|
end
|
100
116
|
|
101
117
|
@@config_callbacks ||= { }
|
data/lib/asir/config.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module ASIR
|
2
|
+
module Description
|
3
|
+
def describe obj, indent = "", more = nil
|
4
|
+
case obj
|
5
|
+
when nil, ASIR::Coder::Identity
|
6
|
+
s = ""; more = nil
|
7
|
+
when ASIR::Transport
|
8
|
+
s = "#{describe(obj.encoder, indent, "->\n")}#{indent}#{obj.class.name}"
|
9
|
+
opts = [ :file, :uri ].
|
10
|
+
select { | x | obj.respond_to?(x) && obj.send(x) != nil }.
|
11
|
+
map { | x | "#{x}: #{obj.send(x).inspect}" } * ","
|
12
|
+
s << "(" << opts << ")" unless opts.empty?
|
13
|
+
case
|
14
|
+
when obj.respond_to?(:transports)
|
15
|
+
s << "->[\n"
|
16
|
+
s << obj.transports.map { | x | describe(x, indent + " ") } * ",\n"
|
17
|
+
s << "]"
|
18
|
+
when obj.respond_to?(:transport)
|
19
|
+
s << "->\n" << describe(obj.transport, indent + " ")
|
20
|
+
end
|
21
|
+
when ASIR::Coder::Chain
|
22
|
+
s = "#{indent}Chain(\n"
|
23
|
+
s << obj.encoders.map { | x | describe(x, indent + " ") } * "->\n"
|
24
|
+
s << ")"
|
25
|
+
else
|
26
|
+
s = "#{indent}#{obj.class.name}"
|
27
|
+
end
|
28
|
+
s << more if more
|
29
|
+
s
|
30
|
+
end
|
31
|
+
|
32
|
+
extend self
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'asir'
|
2
|
+
|
3
|
+
module ASIR; class Environment
|
4
|
+
attr_accessor :phase
|
5
|
+
attr_accessor :verb, :adjective, :object, :identifier
|
6
|
+
attr_accessor :config_rb, :config
|
7
|
+
attr_accessor :log_dir, :log_file, :pid_dir
|
8
|
+
attr_accessor :verbose
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@verbose = 0
|
12
|
+
@exit_code = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def log_dir
|
16
|
+
@log_dir ||= find_writable_directory :log_dir,
|
17
|
+
ENV['ASIR_LOG_DIR'],
|
18
|
+
'/var/log/asir',
|
19
|
+
'~/asir/log',
|
20
|
+
'/tmp'
|
21
|
+
end
|
22
|
+
|
23
|
+
def pid_dir
|
24
|
+
@pid_dir ||= find_writable_directory :pid_dir,
|
25
|
+
ENV['ASIR_PID_DIR'],
|
26
|
+
'/var/run/asir',
|
27
|
+
'~/asir/run',
|
28
|
+
'/tmp'
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_writable_directory kind, *list
|
32
|
+
list.
|
33
|
+
reject { | p | ! p }.
|
34
|
+
map { | p | File.expand_path(p) }.
|
35
|
+
find { | p | File.writable?(p) } or
|
36
|
+
raise "Cannot find writable directory for #{kind}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def pid_file
|
40
|
+
@pid_file ||=
|
41
|
+
"#{pid_dir}/#{asir_basename}.pid"
|
42
|
+
end
|
43
|
+
|
44
|
+
def log_file
|
45
|
+
@log_file ||=
|
46
|
+
"#{log_dir}/#{asir_basename}.log"
|
47
|
+
end
|
48
|
+
|
49
|
+
def asir_basename
|
50
|
+
"asir-#{adjective}-#{object}-#{identifier}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def config_rb
|
54
|
+
@config_rb ||=
|
55
|
+
File.expand_path(ENV['ASIR_CONFIG_RB'] || 'config/asir_config.rb')
|
56
|
+
end
|
57
|
+
|
58
|
+
def config! phase, opts = { }
|
59
|
+
((@config ||= { })[phase] ||= [
|
60
|
+
begin
|
61
|
+
opts[:phase] = phase
|
62
|
+
save = { }
|
63
|
+
opts.each do | k, v |
|
64
|
+
save[k] = send(k)
|
65
|
+
send(:"#{k}=", v)
|
66
|
+
end
|
67
|
+
$stderr.puts "#{self.class} calling #{config_rb} asir.phase=#{phase.inspect} ..." if @verbose >= 1
|
68
|
+
value = config_lambda.call(self)
|
69
|
+
$stderr.puts "#{self.class} calling #{config_rb} asir.phase=#{phase.inspect} DONE" if @verbose >= 1
|
70
|
+
value
|
71
|
+
ensure
|
72
|
+
save.each do | k , v |
|
73
|
+
send(:"#{k}=", v)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
]).first
|
77
|
+
end
|
78
|
+
|
79
|
+
def config_lambda
|
80
|
+
@config_lambda ||=
|
81
|
+
(
|
82
|
+
file = config_rb
|
83
|
+
$stderr.puts "#{self.class} loading #{file} ..." if @verbose >= 1
|
84
|
+
expr = File.read(file)
|
85
|
+
expr = "begin; lambda do | asir |; #{expr}\n end; end"
|
86
|
+
cfg = Object.new.send(:eval, expr, binding, file, 1)
|
87
|
+
# cfg = load file
|
88
|
+
# $stderr.puts "#{self.class} loading #{file} DONE" if @verbose >= 1
|
89
|
+
raise "#{file} did not return a Proc, returned a #{cfg.class}" unless Proc === cfg
|
90
|
+
cfg
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
end; end
|
95
|
+
|
96
|
+
|