cromwell 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +35 -1
- data/VERSION +1 -1
- data/cromwell.gemspec +5 -3
- data/examples/example6.rb +14 -0
- data/lib/cromwell.rb +48 -5
- data/test/test_cromwell.rb +88 -1
- metadata +4 -2
data/README.rdoc
CHANGED
@@ -175,6 +175,37 @@ When run, it goes like this:
|
|
175
175
|
|
176
176
|
Of course, had I press <code>^C</code> right after "See you in a while...", the script would terminate after 1 second at the end of the protected block.
|
177
177
|
|
178
|
+
=== Logging
|
179
|
+
|
180
|
+
If want to see what is going on with Cromwell or have some problems with it, you can use a logger (requires cromwell gem version >= 0.3). If Cromwell is used inside an application that already uses logging, you can use your app's logger. Or you might prefer to use a separate logger.
|
181
|
+
|
182
|
+
Cromwell uses two levels of log messages:
|
183
|
+
|
184
|
+
* <code>Logger::INFO</code> -- when a signal was caught or script is terminated.
|
185
|
+
* <code>Logger::DEBUG</code> -- all sorts of debugging information: setting up and restoring traps, calling methods and yielding block. Probably not useful for you, unless you have some problems with Cromwell or are messing with the code.
|
186
|
+
|
187
|
+
Here's an example of logger usage:
|
188
|
+
|
189
|
+
Cromwell.logger = Logger.new(STDOUT)
|
190
|
+
Cromwell.logger.level = Logger::INFO
|
191
|
+
|
192
|
+
puts 'See you in a while...'
|
193
|
+
Cromwell.protect {
|
194
|
+
sleep 10
|
195
|
+
}
|
196
|
+
puts "You're still here?"
|
197
|
+
|
198
|
+
When run, this script will log messages on <code>STDOUT</code>:
|
199
|
+
|
200
|
+
$ ruby examples/example6.rb
|
201
|
+
See you in a while...
|
202
|
+
^CI, [2010-01-14T11:59:29.246851 #19011] INFO -- : Caught signal INT -- ignoring.
|
203
|
+
^CI, [2010-01-14T11:59:31.558532 #19011] INFO -- : Caught signal INT -- ignoring.
|
204
|
+
^CI, [2010-01-14T11:59:36.270395 #19011] INFO -- : Caught signal INT -- ignoring.
|
205
|
+
[ ten seconds pass... ]
|
206
|
+
I, [2010-01-14T11:59:37.872514 #19011] INFO -- : Exiting because should_exit is true
|
207
|
+
$
|
208
|
+
|
178
209
|
== Compatibility
|
179
210
|
|
180
211
|
Works for me. Tested on Mac OS X 10.4--10.6 and a little bit on Debian Linux. If it works for you too, I'd be glad to know. Cromwell's reliability depends heavily on your operating system's signals implementation reliability (which may not be very stable on some systems).
|
@@ -182,10 +213,13 @@ Works for me. Tested on Mac OS X 10.4--10.6 and a little bit on Debian Linux. If
|
|
182
213
|
== To Do list
|
183
214
|
|
184
215
|
* Allow to customize behavior after catching a signal. Right now, the script is terminated after the protected block is done (even if the signal would not normally cause script termination).
|
185
|
-
* Add logger support.
|
186
216
|
|
187
217
|
== Changelog
|
188
218
|
|
219
|
+
=== 0.3
|
220
|
+
|
221
|
+
* Added logger support.
|
222
|
+
|
189
223
|
=== 0.2
|
190
224
|
|
191
225
|
* Remove traps when they are not needed anymore and restore original traps.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/cromwell.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{cromwell}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Przemyslaw Kowalczyk"]
|
12
|
-
s.date = %q{2010-01-
|
12
|
+
s.date = %q{2010-01-14}
|
13
13
|
s.description = %q{A very simple wrapper over Signal#trap method that allows you to easily protect your scripts from being killed while they are doing something that should not be interrupted (e.g. interacting with some non-transactional service) or is too costly to restart (e.g. long computations). }
|
14
14
|
s.email = %q{szeryf@negativeiq.pl}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |s|
|
|
29
29
|
"examples/example3.rb",
|
30
30
|
"examples/example4.rb",
|
31
31
|
"examples/example5.rb",
|
32
|
+
"examples/example6.rb",
|
32
33
|
"lib/cromwell.rb",
|
33
34
|
"test/helper.rb",
|
34
35
|
"test/test_cromwell.rb"
|
@@ -45,7 +46,8 @@ Gem::Specification.new do |s|
|
|
45
46
|
"examples/example2.rb",
|
46
47
|
"examples/example3.rb",
|
47
48
|
"examples/example4.rb",
|
48
|
-
"examples/example5.rb"
|
49
|
+
"examples/example5.rb",
|
50
|
+
"examples/example6.rb"
|
49
51
|
]
|
50
52
|
|
51
53
|
if s.respond_to? :specification_version then
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# ensure that we use ../lib/cromwell.rb, not the installed gem
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
require 'cromwell'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
Cromwell.logger = Logger.new(STDOUT)
|
8
|
+
Cromwell.logger.level = Logger::INFO
|
9
|
+
|
10
|
+
puts 'See you in a while...'
|
11
|
+
Cromwell.protect {
|
12
|
+
sleep 10
|
13
|
+
}
|
14
|
+
puts "You're still here?"
|
data/lib/cromwell.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
class Cromwell
|
2
2
|
DEFAULT_SIGNAL_LIST = %w[INT TERM HUP QUIT].freeze
|
3
3
|
|
4
|
+
@@logger = nil
|
5
|
+
@@should_exit = false
|
6
|
+
@@protected = false
|
7
|
+
@@old_traps = {}
|
8
|
+
|
4
9
|
class << self
|
5
10
|
# call-seq:
|
6
11
|
# Cromwell.protect(*signals) { ... some code ... }
|
@@ -14,12 +19,15 @@ class Cromwell
|
|
14
19
|
# Without parameters, the code is protected from the signals in DEFAULT_SIGNAL_LIST.
|
15
20
|
# More info and examples in README.rdoc.
|
16
21
|
def protect *signals
|
22
|
+
debug "Protect called with [#{signals * ', '}]"
|
17
23
|
set_up_traps(signals.empty? ? DEFAULT_SIGNAL_LIST : signals.flatten)
|
18
24
|
@@should_exit = false
|
19
25
|
@@protected = true
|
20
26
|
if block_given?
|
21
27
|
begin
|
28
|
+
debug "About to yield to block."
|
22
29
|
yield
|
30
|
+
debug "After yielding to block."
|
23
31
|
ensure
|
24
32
|
unprotect
|
25
33
|
end
|
@@ -33,8 +41,13 @@ class Cromwell
|
|
33
41
|
# if signal was caught earlier (so any <code>at_exit</code> code will be executed).
|
34
42
|
# The protect method calls this automatically when executed with a block.
|
35
43
|
def unprotect
|
44
|
+
debug "Unprotect called"
|
36
45
|
@@protected = false
|
37
|
-
|
46
|
+
debug "should_exit? = #{@@should_exit}"
|
47
|
+
if @@should_exit
|
48
|
+
info "Exiting because should_exit is true"
|
49
|
+
exit
|
50
|
+
end
|
38
51
|
restore_old_traps
|
39
52
|
end
|
40
53
|
|
@@ -64,33 +77,63 @@ class Cromwell
|
|
64
77
|
@@protected
|
65
78
|
end
|
66
79
|
|
80
|
+
# call-seq:
|
81
|
+
# Cromwell.logger
|
82
|
+
#
|
83
|
+
# Returns logger. There is no default logger, so if you haven't set this before, it will be nil.
|
84
|
+
def logger
|
85
|
+
@@logger
|
86
|
+
end
|
87
|
+
|
88
|
+
# call-seq:
|
89
|
+
# Cromwell.logger = some_logger
|
90
|
+
#
|
91
|
+
# Set a logger for Cromwell.
|
92
|
+
def logger= logger
|
93
|
+
@@logger = logger
|
94
|
+
end
|
95
|
+
|
67
96
|
private
|
68
97
|
def set_up_traps signals
|
69
|
-
signals.each
|
98
|
+
signals.each do |signal|
|
99
|
+
old_trap = set_up_trap signal
|
100
|
+
stash old_trap, signal
|
101
|
+
end
|
70
102
|
end
|
71
103
|
|
72
104
|
def set_up_trap signal
|
73
|
-
|
105
|
+
debug "Setting trap for #{signal}"
|
106
|
+
trap signal do
|
74
107
|
if @@protected
|
108
|
+
info "Caught signal #{signal} -- ignoring."
|
75
109
|
@@should_exit = true
|
76
110
|
"IGNORE"
|
77
111
|
else
|
112
|
+
info "Caught signal #{signal} -- exiting."
|
78
113
|
exit
|
79
114
|
end
|
80
115
|
end
|
81
|
-
stash old_trap, signal
|
82
116
|
end
|
83
117
|
|
84
118
|
def stash old_trap, signal
|
85
|
-
|
119
|
+
debug "Stashing old trap #{old_trap} for #{signal}"
|
86
120
|
@@old_traps[signal] = old_trap
|
87
121
|
end
|
88
122
|
|
89
123
|
def restore_old_traps
|
90
124
|
@@old_traps.each do |signal, old_trap|
|
125
|
+
debug "Restoring old trap #{old_trap} for #{signal}"
|
91
126
|
trap signal, old_trap
|
92
127
|
end
|
93
128
|
@@old_traps = {}
|
94
129
|
end
|
130
|
+
|
131
|
+
def debug msg
|
132
|
+
@@logger.debug msg if @@logger
|
133
|
+
end
|
134
|
+
|
135
|
+
def info msg
|
136
|
+
@@logger.info msg if @@logger
|
137
|
+
end
|
95
138
|
end
|
96
139
|
end
|
data/test/test_cromwell.rb
CHANGED
@@ -115,9 +115,52 @@ class TestCromwell < Test::Unit::TestCase
|
|
115
115
|
assert Cromwell.protected?
|
116
116
|
end
|
117
117
|
|
118
|
+
context "with a logger" do
|
119
|
+
setup do
|
120
|
+
@log = stub :debug => true
|
121
|
+
Cromwell.logger = @log
|
122
|
+
end
|
123
|
+
|
124
|
+
teardown do
|
125
|
+
Cromwell.logger = nil
|
126
|
+
end
|
127
|
+
|
128
|
+
should "log about being called" do
|
129
|
+
@log.expects(:debug).with("Protect called with []")
|
130
|
+
Cromwell.protect { i = 1 }
|
131
|
+
end
|
132
|
+
|
133
|
+
should "log about being called with parameters" do
|
134
|
+
@log.expects(:debug).with("Protect called with [HUP, TERM]")
|
135
|
+
Cromwell.protect("HUP", "TERM") { i = 1 }
|
136
|
+
end
|
137
|
+
|
138
|
+
should "log about setting traps" do
|
139
|
+
@log.expects(:debug).with("Setting trap for HUP")
|
140
|
+
@log.expects(:debug).with("Setting trap for TERM")
|
141
|
+
Cromwell.protect("HUP", "TERM") { i = 1 }
|
142
|
+
end
|
143
|
+
|
144
|
+
should "log about stashing old traps" do
|
145
|
+
Signal.trap "HUP", proc {}
|
146
|
+
Signal.trap "TERM", "DEFAULT"
|
147
|
+
@log.expects(:debug).with(regexp_matches(/^Stashing old trap #<Proc:.+> for HUP$/))
|
148
|
+
@log.expects(:debug).with('Stashing old trap DEFAULT for TERM')
|
149
|
+
Cromwell.protect("HUP", "TERM") { i = 1 }
|
150
|
+
end
|
151
|
+
|
152
|
+
should "log about restoring old traps" do
|
153
|
+
Signal.trap "HUP", proc {}
|
154
|
+
Signal.trap "TERM", "DEFAULT"
|
155
|
+
@log.expects(:debug).with(regexp_matches(/^Restoring old trap #<Proc:.+> for HUP$/))
|
156
|
+
@log.expects(:debug).with('Restoring old trap DEFAULT for TERM')
|
157
|
+
Cromwell.protect("HUP", "TERM") { i = 1 }
|
158
|
+
end
|
159
|
+
end # with a logger
|
160
|
+
|
118
161
|
end # method protect
|
119
162
|
|
120
|
-
context "method protect with block" do
|
163
|
+
context "method protect with a block" do
|
121
164
|
should "yield to block" do
|
122
165
|
im_in_ur_blok_touchin_ur_vars = false
|
123
166
|
Cromwell.protect {
|
@@ -136,6 +179,28 @@ class TestCromwell < Test::Unit::TestCase
|
|
136
179
|
assert Cromwell.protected?
|
137
180
|
}
|
138
181
|
end
|
182
|
+
|
183
|
+
context "with a logger" do
|
184
|
+
setup do
|
185
|
+
@log = stub :debug => true
|
186
|
+
Cromwell.logger = @log
|
187
|
+
end
|
188
|
+
|
189
|
+
teardown do
|
190
|
+
Cromwell.logger = nil
|
191
|
+
end
|
192
|
+
|
193
|
+
should "log before yield" do
|
194
|
+
@log.expects(:debug).with('About to yield to block.')
|
195
|
+
Cromwell.protect { i = 1 }
|
196
|
+
end
|
197
|
+
|
198
|
+
should "log after yield" do
|
199
|
+
@log.expects(:debug).with('After yielding to block.')
|
200
|
+
Cromwell.protect { i = 1 }
|
201
|
+
end
|
202
|
+
end # with a logger
|
203
|
+
|
139
204
|
end # method protect with block
|
140
205
|
|
141
206
|
context "method unprotect" do
|
@@ -150,6 +215,28 @@ class TestCromwell < Test::Unit::TestCase
|
|
150
215
|
Cromwell.expects(:exit)
|
151
216
|
Cromwell.unprotect
|
152
217
|
end
|
218
|
+
|
219
|
+
context "with a logger" do
|
220
|
+
setup do
|
221
|
+
@log = stub :debug => true
|
222
|
+
Cromwell.logger = @log
|
223
|
+
Cromwell.should_exit = false
|
224
|
+
end
|
225
|
+
|
226
|
+
teardown do
|
227
|
+
Cromwell.logger = nil
|
228
|
+
end
|
229
|
+
|
230
|
+
should "log about being called" do
|
231
|
+
@log.expects(:debug).with("Unprotect called")
|
232
|
+
Cromwell.unprotect
|
233
|
+
end
|
234
|
+
|
235
|
+
should "log about should_exit value" do
|
236
|
+
@log.expects(:debug).with("should_exit? = false")
|
237
|
+
Cromwell.unprotect
|
238
|
+
end
|
239
|
+
end # with a logger
|
153
240
|
end # method unprotect
|
154
241
|
|
155
242
|
context "should_exit=" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cromwell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Przemyslaw Kowalczyk
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-14 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- examples/example3.rb
|
55
55
|
- examples/example4.rb
|
56
56
|
- examples/example5.rb
|
57
|
+
- examples/example6.rb
|
57
58
|
- lib/cromwell.rb
|
58
59
|
- test/helper.rb
|
59
60
|
- test/test_cromwell.rb
|
@@ -93,3 +94,4 @@ test_files:
|
|
93
94
|
- examples/example3.rb
|
94
95
|
- examples/example4.rb
|
95
96
|
- examples/example5.rb
|
97
|
+
- examples/example6.rb
|