billymeltdown-looper 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +46 -0
- data/lib/looper.rb +71 -0
- data/looper.gemspec +17 -0
- metadata +56 -0
data/README.textile
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
Looper is a dead simple Ruby module for daemonizing your code, meant for use with Rails' script/runner. No forking involved, no detaching, simply running a nice healthy loop, but allowing your code to bail out of it, and making it responsive to signals.
|
2
|
+
|
3
|
+
You implement a class like "DoSomething" that checks for new message objects and then does something to them. This class will include Looper in order to easily loop, respond to shutdown signals, and it can then be run via script/runner as a daemon.
|
4
|
+
|
5
|
+
The loop handles sleeping between runs, and will catch any unhandled exceptions that bubble up and keep on truckin'. Thus, if you want to exit on a particular exception, you've got to rescue it in your code and set @\@run@ to @false@.
|
6
|
+
|
7
|
+
Here's an example usage:
|
8
|
+
|
9
|
+
<pre>
|
10
|
+
require 'looper'
|
11
|
+
|
12
|
+
class DoSomething
|
13
|
+
include Looper
|
14
|
+
|
15
|
+
attr_accessor :run
|
16
|
+
|
17
|
+
def initialize(config)
|
18
|
+
@run = true
|
19
|
+
# do config stuff, etc...
|
20
|
+
@sleep = config[:sleep].nil? ? 60 : config[:sleep]
|
21
|
+
end # initialize
|
22
|
+
|
23
|
+
def run
|
24
|
+
loopme(@sleep) do
|
25
|
+
begin
|
26
|
+
# this is where the meat of your code goes...
|
27
|
+
messages = twitter.direct_messages({:since => since.strftime("%a, %d %b %Y %H:%M:%S %Z")})
|
28
|
+
rescue Twitter::EpicFailure => e
|
29
|
+
puts "bailing out, dude!"
|
30
|
+
# set run to false to put the kabosh on the next run
|
31
|
+
@run = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# and here's how we kick it off:
|
38
|
+
DoSomething.new( { :sleep => 10 } ).run
|
39
|
+
|
40
|
+
</pre>
|
41
|
+
|
42
|
+
Now we can just kick that off any way we like and background the process, but we tend to use it with script/runner in our Rails environments to have access to our models and such. It boils down to:
|
43
|
+
|
44
|
+
$ nohup script/runner -e RAILS_ENV /path/to/DoSomething.rb
|
45
|
+
|
46
|
+
And then looking up the PID by matching on /path/to/DoSomething.rb via grep and use kill to send the term signal.
|
data/lib/looper.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright (c) 2008 Zetetic LLC
|
2
|
+
|
3
|
+
# Permission is hereby granted, free of charge, to any person
|
4
|
+
# obtaining a copy of this software and associated documentation
|
5
|
+
# files (the "Software"), to deal in the Software without
|
6
|
+
# restriction, including without limitation the rights to use,
|
7
|
+
# copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the
|
9
|
+
# Software is furnished to do so, subject to the following
|
10
|
+
# conditions:
|
11
|
+
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
module Looper
|
25
|
+
|
26
|
+
def trap_signals
|
27
|
+
sigtrap = proc {
|
28
|
+
puts "caught trapped signal, shutting down"
|
29
|
+
@run = false
|
30
|
+
}
|
31
|
+
["SIGTERM", "SIGINT", "SIGHUP"].each do |signal|
|
32
|
+
trap signal, sigtrap
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def loopme(run_every = 10)
|
37
|
+
# we don't want to delay output to sdtout until the program stops, we want feedback!
|
38
|
+
$stdout.sync=true
|
39
|
+
|
40
|
+
trap_signals
|
41
|
+
|
42
|
+
@run = true
|
43
|
+
|
44
|
+
puts "#{Time.now} process started with #{run_every} loop. kill #{Process.pid} to stop"
|
45
|
+
|
46
|
+
last_run = Time.now - run_every.seconds - 1
|
47
|
+
while (@run) do
|
48
|
+
now = Time.now
|
49
|
+
if last_run + run_every.seconds < now
|
50
|
+
begin
|
51
|
+
yield
|
52
|
+
rescue Exception => e
|
53
|
+
puts "Uncaught exception bubbled up: \n#{e.class}: #{e.message}\n\t#{e.backtrace.join("\n\t")} "
|
54
|
+
end
|
55
|
+
last_run = now
|
56
|
+
end
|
57
|
+
sleep(2)
|
58
|
+
end
|
59
|
+
puts "#{Time.now} shutting down"
|
60
|
+
end
|
61
|
+
|
62
|
+
def write_pid(filename, pid)
|
63
|
+
file = File.new(filename, "w")
|
64
|
+
file.print pid.to_s
|
65
|
+
file.close
|
66
|
+
end
|
67
|
+
|
68
|
+
def exit_loop
|
69
|
+
@run = false
|
70
|
+
end
|
71
|
+
end
|
data/looper.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "looper"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.date = "2009-01-21"
|
5
|
+
s.summary = "Module for really simple daemons"
|
6
|
+
s.email = "wgray@zetetic.net"
|
7
|
+
s.homepage = "http://github.com/billymeltdown/looper"
|
8
|
+
s.description = "Looper is a module that your class can use to become a really, really simple daemon"
|
9
|
+
s.has_rdoc = false
|
10
|
+
s.authors = ["Billy Gray", "Stephen Lombardo"]
|
11
|
+
s.files = [ "README.textile",
|
12
|
+
"looper.gemspec",
|
13
|
+
"lib/looper.rb" ]
|
14
|
+
s.test_files = [ ]
|
15
|
+
s.rdoc_options = [ ]
|
16
|
+
s.extra_rdoc_files = [ ]
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: billymeltdown-looper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Billy Gray
|
8
|
+
- Stephen Lombardo
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-01-21 00:00:00 -08:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: Looper is a module that your class can use to become a really, really simple daemon
|
18
|
+
email: wgray@zetetic.net
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files: []
|
24
|
+
|
25
|
+
files:
|
26
|
+
- README.textile
|
27
|
+
- looper.gemspec
|
28
|
+
- lib/looper.rb
|
29
|
+
has_rdoc: false
|
30
|
+
homepage: http://github.com/billymeltdown/looper
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: "0"
|
41
|
+
version:
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
requirements: []
|
49
|
+
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 1.2.0
|
52
|
+
signing_key:
|
53
|
+
specification_version: 2
|
54
|
+
summary: Module for really simple daemons
|
55
|
+
test_files: []
|
56
|
+
|