loops 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +21 -0
- data/VERSION.yml +2 -2
- data/lib/loops/cli/commands.rb +1 -6
- data/lib/loops/cli/options.rb +12 -6
- data/lib/loops/command.rb +5 -0
- data/lib/loops/commands/list_command.rb +4 -0
- data/lib/loops/commands/stats_command.rb +4 -0
- data/lib/loops/commands/stop_command.rb +4 -0
- data/lib/loops/engine.rb +6 -12
- data/lib/loops/process_manager.rb +5 -21
- data/loops.gemspec +3 -3
- data/spec/rails/app/loops/complex_loop.rb +1 -1
- metadata +5 -12
data/README.rdoc
CHANGED
@@ -217,6 +217,27 @@ not support demonization in JRuby and never tested the code on Ruby 1.9. Obvious
|
|
217
217
|
of JVM limitations you won't be able to use <tt>fork</tt> workers engine in JRuby, but
|
218
218
|
threaded workers do pretty well.
|
219
219
|
|
220
|
+
Recommended version of ruby ro run loops is Ruby Enterprise Edition. This is because we
|
221
|
+
have a support for their Copy-On-Write friendly garbage collector that makes your loops
|
222
|
+
much smaller in memory (since they share the most of the code). Even with one loop process
|
223
|
+
you'd save some memory because your loop monitor process would share most of the memory with
|
224
|
+
the loop itself. When you run on RubyEE, you could use <tt>loops stats</tt> command to get
|
225
|
+
detailed loops memory stats:
|
226
|
+
|
227
|
+
[root@analyics current]# ./script/loops stats
|
228
|
+
|
229
|
+
--------- Loops processes ----------
|
230
|
+
PID PPID VMSize Private Name
|
231
|
+
------------------------------------
|
232
|
+
9062 1 199.3 MB 32.4 MB loops monitor: activemq
|
233
|
+
9234 9062 211.9 MB 37.5 MB loop worker: activemq
|
234
|
+
9251 9062 213.3 MB 38.4 MB loop worker: activemq
|
235
|
+
9267 9062 211.9 MB 37.1 MB loop worker: activemq
|
236
|
+
9268 9062 211.9 MB 38.0 MB loop worker: activemq
|
237
|
+
### Processes: 5
|
238
|
+
### Total private dirty RSS: 183.33 MB
|
239
|
+
|
240
|
+
|
220
241
|
|
221
242
|
== Migrating from pre-2.0 releases
|
222
243
|
|
data/VERSION.yml
CHANGED
data/lib/loops/cli/commands.rb
CHANGED
@@ -81,12 +81,7 @@ module Loops
|
|
81
81
|
# Finds, instantiates and invokes a command.
|
82
82
|
#
|
83
83
|
def run!
|
84
|
-
|
85
|
-
cmd.invoke(engine, options)
|
86
|
-
else
|
87
|
-
STDERR << option_parser
|
88
|
-
exit
|
89
|
-
end
|
84
|
+
@command.invoke(engine, options)
|
90
85
|
end
|
91
86
|
|
92
87
|
# Find and return an instance of {Command} by command name.
|
data/lib/loops/cli/options.rb
CHANGED
@@ -129,11 +129,8 @@ module Loops
|
|
129
129
|
# Loops root
|
130
130
|
Loops.loops_root = options.delete(:loops_root)
|
131
131
|
|
132
|
-
extract_command!
|
133
|
-
|
134
|
-
puts option_parser
|
135
|
-
exit
|
136
|
-
end
|
132
|
+
@command = extract_command!
|
133
|
+
options[:framework] = 'none' unless @command.requires_bootstrap?
|
137
134
|
|
138
135
|
bootstrap!
|
139
136
|
start_engine!
|
@@ -154,7 +151,16 @@ module Loops
|
|
154
151
|
#
|
155
152
|
def extract_command!
|
156
153
|
options[:command], *options[:args] = args
|
157
|
-
options[:command]
|
154
|
+
if options[:command].nil? || options[:command] == 'help'
|
155
|
+
puts option_parser
|
156
|
+
exit
|
157
|
+
end
|
158
|
+
|
159
|
+
unless command = find_command(options[:command])
|
160
|
+
STDERR << option_parser
|
161
|
+
exit
|
162
|
+
end
|
163
|
+
command
|
158
164
|
end
|
159
165
|
|
160
166
|
# Detect the application root directory (contatining "app"
|
data/lib/loops/command.rb
CHANGED
data/lib/loops/engine.rb
CHANGED
@@ -181,20 +181,14 @@ class Loops::Engine
|
|
181
181
|
end
|
182
182
|
|
183
183
|
def setup_signals
|
184
|
-
|
185
|
-
warn "Received a
|
186
|
-
@pm.
|
184
|
+
stop = proc {
|
185
|
+
warn "Received a signal... stopping..."
|
186
|
+
@pm.start_shutdown!
|
187
187
|
}
|
188
188
|
|
189
|
-
trap('
|
190
|
-
|
191
|
-
|
192
|
-
}
|
193
|
-
|
194
|
-
trap('EXIT') {
|
195
|
-
warn "Received a EXIT 'signal'... stopping..."
|
196
|
-
@pm.stop_workers!
|
197
|
-
}
|
189
|
+
trap('TERM', stop)
|
190
|
+
trap('INT', stop)
|
191
|
+
trap('EXIT', stop)
|
198
192
|
end
|
199
193
|
|
200
194
|
def fix_ar_after_fork
|
@@ -37,6 +37,11 @@ module Loops
|
|
37
37
|
sleep(@config['poll_period'])
|
38
38
|
end
|
39
39
|
ensure
|
40
|
+
logger.info("Workers monitoring loop is finished, starting shutdown...")
|
41
|
+
# Send out stop signals
|
42
|
+
stop_workers(false)
|
43
|
+
|
44
|
+
# Wait for all the workers to die
|
40
45
|
unless wait_for_workers(10)
|
41
46
|
logger.info("Some workers are still alive after 10 seconds of waiting. Killing them...")
|
42
47
|
stop_workers(true)
|
@@ -72,12 +77,8 @@ module Loops
|
|
72
77
|
end
|
73
78
|
|
74
79
|
def stop_workers(force = false)
|
75
|
-
# Return if already shuting down (and not forced to stop)
|
76
|
-
return if shutdown? && !force
|
77
|
-
|
78
80
|
# Set shutdown flag
|
79
81
|
logger.info("Stopping workers#{force ? ' (forced)' : ''}...")
|
80
|
-
start_shutdown!
|
81
82
|
|
82
83
|
# Termination loop
|
83
84
|
@worker_pools.each do |name, pool|
|
@@ -85,23 +86,6 @@ module Loops
|
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
88
|
-
def stop_workers!
|
89
|
-
# return if already shutting down
|
90
|
-
return if shutdown?
|
91
|
-
|
92
|
-
# Set shutdown flag
|
93
|
-
start_shutdown!
|
94
|
-
|
95
|
-
# Ask gently to stop
|
96
|
-
stop_workers(false)
|
97
|
-
|
98
|
-
# Give it a second
|
99
|
-
sleep(1)
|
100
|
-
|
101
|
-
# Forcefully stop the workers
|
102
|
-
stop_workers(true)
|
103
|
-
end
|
104
|
-
|
105
89
|
def shutdown?
|
106
90
|
@shutdown
|
107
91
|
end
|
data/loops.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{loops}
|
8
|
-
s.version = "2.0.
|
8
|
+
s.version = "2.0.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alexey Kovyrin", "Dmytro Shteflyuk"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-31}
|
13
13
|
s.description = %q{Loops is a small and lightweight framework for Ruby on Rails, Merb and other ruby frameworks created to support simple background loops in your application which are usually used to do some background data processing on your servers (queue workers, batch tasks processors, etc).}
|
14
14
|
s.email = %q{alexey@kovyrin.net}
|
15
15
|
s.executables = ["loops", "loops-memory-stats"]
|
@@ -70,7 +70,7 @@ Gem::Specification.new do |s|
|
|
70
70
|
s.homepage = %q{http://github.com/kovyrin/loops}
|
71
71
|
s.rdoc_options = ["--charset=UTF-8"]
|
72
72
|
s.require_paths = ["lib"]
|
73
|
-
s.rubygems_version = %q{1.3.
|
73
|
+
s.rubygems_version = %q{1.3.5}
|
74
74
|
s.summary = %q{Simple background loops framework for ruby}
|
75
75
|
s.test_files = [
|
76
76
|
"spec/loop_lock_spec.rb",
|
metadata
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loops
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 2
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
version: 2.0.1
|
4
|
+
version: 2.0.2
|
10
5
|
platform: ruby
|
11
6
|
authors:
|
12
7
|
- Alexey Kovyrin
|
@@ -15,7 +10,7 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date: 2010-03-
|
13
|
+
date: 2010-03-31 00:00:00 -04:00
|
19
14
|
default_executable:
|
20
15
|
dependencies: []
|
21
16
|
|
@@ -91,20 +86,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
86
|
requirements:
|
92
87
|
- - ">="
|
93
88
|
- !ruby/object:Gem::Version
|
94
|
-
segments:
|
95
|
-
- 0
|
96
89
|
version: "0"
|
90
|
+
version:
|
97
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
92
|
requirements:
|
99
93
|
- - ">="
|
100
94
|
- !ruby/object:Gem::Version
|
101
|
-
segments:
|
102
|
-
- 0
|
103
95
|
version: "0"
|
96
|
+
version:
|
104
97
|
requirements: []
|
105
98
|
|
106
99
|
rubyforge_project:
|
107
|
-
rubygems_version: 1.3.
|
100
|
+
rubygems_version: 1.3.5
|
108
101
|
signing_key:
|
109
102
|
specification_version: 3
|
110
103
|
summary: Simple background loops framework for ruby
|