asir 0.2.0 → 1.0.1
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 +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
|
+
|