djinn 0.0.9 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +54 -4
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/djinn.gemspec +1 -1
- data/lib/djinn.rb +2 -2
- data/lib/djinn/dsl.rb +4 -0
- data/lib/djinn/logging.rb +11 -9
- data/lib/djinn/pid_file.rb +2 -1
- data/lib/djinn/rails.rb +1 -0
- data/lib/djinn/tonic.rb +13 -19
- metadata +3 -3
data/README.rdoc
CHANGED
@@ -2,10 +2,17 @@
|
|
2
2
|
|
3
3
|
Djinn is a very basic helper for building simple daemons.
|
4
4
|
|
5
|
+
In Arabian mythology a Djinn is a supernatural creature which occupies a
|
6
|
+
parallel world to that of mankind.
|
7
|
+
|
5
8
|
== Documentation
|
6
9
|
|
7
10
|
http://rdoc.info/projects/craigp/djinn
|
8
11
|
|
12
|
+
== Installation
|
13
|
+
|
14
|
+
gem install djinn
|
15
|
+
|
9
16
|
== Non-Rails Example (old non-DSL way, will be deprecated soon-ish)
|
10
17
|
|
11
18
|
#!/usr/bin/env ruby
|
@@ -21,7 +28,10 @@ http://rdoc.info/projects/craigp/djinn
|
|
21
28
|
# in Djinn, which does nothing useful. Make sure your method accepts
|
22
29
|
# a config hash, even if it doesn't use it.
|
23
30
|
def perform options
|
24
|
-
|
31
|
+
while
|
32
|
+
log "ZOMG! A Djinn?"
|
33
|
+
sleep(5)
|
34
|
+
do
|
25
35
|
end
|
26
36
|
|
27
37
|
# Strictly optional, lets you do stuff when the Djinn daemon stops.
|
@@ -83,7 +93,10 @@ Using the same silly example, you can do this:
|
|
83
93
|
|
84
94
|
djinn do
|
85
95
|
on :start do
|
86
|
-
|
96
|
+
while
|
97
|
+
log "ZOMG! A Djinn?"
|
98
|
+
sleep(5)
|
99
|
+
end
|
87
100
|
end
|
88
101
|
|
89
102
|
on :exit do
|
@@ -94,7 +107,7 @@ Using the same silly example, you can do this:
|
|
94
107
|
end
|
95
108
|
|
96
109
|
Much cleaner and prettier, and no horrible *super* required. Available
|
97
|
-
actions to the *on* method are
|
110
|
+
actions to the *on* method are :start, :stop and :exit
|
98
111
|
|
99
112
|
Run it in the foreground in the same way:
|
100
113
|
|
@@ -126,7 +139,11 @@ If you need to man-handle the internals and stuff, it yields itself:
|
|
126
139
|
djinn.config[:omghax] = "Groovy, baby"
|
127
140
|
end
|
128
141
|
|
129
|
-
|
142
|
+
Starting in the background is the same as before, call *start* instead of *run*:
|
143
|
+
|
144
|
+
djinn.start
|
145
|
+
|
146
|
+
The Rails Djinns can be built in exactly the same way as this.
|
130
147
|
|
131
148
|
== Rails Example
|
132
149
|
|
@@ -139,6 +156,7 @@ times a book has been read.
|
|
139
156
|
Create a file in RAILS_ROOT/lib or somewhere similar:
|
140
157
|
|
141
158
|
require 'djinn/rails'
|
159
|
+
require 'eventmachine'
|
142
160
|
|
143
161
|
class BookDjinn
|
144
162
|
|
@@ -163,6 +181,38 @@ Create a file in RAILS_ROOT/lib or somewhere similar:
|
|
163
181
|
end
|
164
182
|
|
165
183
|
end
|
184
|
+
|
185
|
+
(And, the new more awesome way:)
|
186
|
+
|
187
|
+
require 'djinn/rails'
|
188
|
+
require 'eventmachine'
|
189
|
+
|
190
|
+
class BookDjinn
|
191
|
+
|
192
|
+
BOOK_WORKER_INTERVAL = 5
|
193
|
+
|
194
|
+
include Djinn::Rails
|
195
|
+
|
196
|
+
djinn do
|
197
|
+
|
198
|
+
on :start do
|
199
|
+
EM.run do
|
200
|
+
log "Workers will run every #{BOOK_WORKER_INTERVAL} secs"
|
201
|
+
EM::PeriodicTimer.new(BOOK_WORKER_INTERVAL) do
|
202
|
+
log "There are #{Book.count} book(s) in the database"
|
203
|
+
log "Updating read counts for all books.."
|
204
|
+
Book.all.each &:read!
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
on :exit do
|
210
|
+
EM.stop
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
end
|
166
216
|
|
167
217
|
Right, now you need to start it somehow. The easiest way is to create a file
|
168
218
|
in RAILS_ROOT/scripts and pop this in it:
|
data/Rakefile
CHANGED
@@ -18,9 +18,9 @@ begin
|
|
18
18
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
19
19
|
end
|
20
20
|
Jeweler::GemcutterTasks.new
|
21
|
-
Jeweler::RubyforgeTasks.new do |rubyforge|
|
22
|
-
|
23
|
-
end
|
21
|
+
# Jeweler::RubyforgeTasks.new do |rubyforge|
|
22
|
+
# rubyforge.doc_task = "rdoc"
|
23
|
+
# end
|
24
24
|
rescue LoadError
|
25
25
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
26
26
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/djinn.gemspec
CHANGED
data/lib/djinn.rb
CHANGED
@@ -4,8 +4,8 @@ require 'yaml'
|
|
4
4
|
require 'djinn/base'
|
5
5
|
require 'djinn/dsl'
|
6
6
|
|
7
|
-
#
|
8
|
-
#
|
7
|
+
# In Arabian mythology a Djinn is a supernatural creature which occupies a
|
8
|
+
# parallel world to that of mankind
|
9
9
|
module Djinn
|
10
10
|
|
11
11
|
include Djinn::Base
|
data/lib/djinn/dsl.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
module Djinn
|
2
|
+
# Defines the awesomesauce DSL for a whole new generation of Djinn
|
2
3
|
module Dsl
|
3
4
|
|
5
|
+
# Start your Djinn definition
|
4
6
|
def djinn &block
|
5
7
|
@dsl_helper = DslHelper.new(&block)
|
6
8
|
@dsl_helper.actions.each do |action, proc|
|
@@ -21,6 +23,7 @@ module Djinn
|
|
21
23
|
instance_eval(&block)
|
22
24
|
end
|
23
25
|
|
26
|
+
# Define an action that will be performed by a Djinn
|
24
27
|
def on action, &block
|
25
28
|
acceptable_actions = %w(start stop exit)
|
26
29
|
raise DslActionError.new("\"#{action}\" is unrecognized, please use one of: #{acceptable_actions.join(', ')}") \
|
@@ -30,6 +33,7 @@ module Djinn
|
|
30
33
|
|
31
34
|
end
|
32
35
|
|
36
|
+
# This error means you screwed something up in your action definition
|
33
37
|
class DslActionError < Exception; end
|
34
38
|
|
35
39
|
end
|
data/lib/djinn/logging.rb
CHANGED
@@ -1,31 +1,33 @@
|
|
1
1
|
module Djinn
|
2
|
+
# Logging Helper Class of Awesomeness
|
2
3
|
module Logging
|
3
|
-
|
4
|
-
|
5
|
-
puts "#{Time.now.strftime("%m/%d/%Y %H:%M:%S")}: #{msg}"
|
6
|
-
STDOUT.flush
|
7
|
-
end
|
8
|
-
|
4
|
+
|
5
|
+
# Log something to STDOUT, or wherever it's been redirected to
|
9
6
|
def log msg
|
10
7
|
puts "#{Time.now.strftime("%m/%d/%Y %H:%M:%S")}: #{msg}"
|
11
8
|
STDOUT.flush
|
12
9
|
end
|
13
10
|
|
11
|
+
# Make some text *green*
|
14
12
|
def green text
|
15
13
|
colorize 32, text
|
16
14
|
end
|
17
15
|
|
16
|
+
# Make some text *red*
|
18
17
|
def red text
|
19
18
|
colorize 31, text
|
20
19
|
end
|
21
20
|
|
21
|
+
# Make some text *cyan*
|
22
22
|
def cyan text
|
23
23
|
colorize 36, text
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
private
|
27
|
+
|
28
|
+
def colorize color, text
|
29
|
+
"\033[#{color}m#{text}\033[0m"
|
30
|
+
end
|
29
31
|
|
30
32
|
end
|
31
33
|
end
|
data/lib/djinn/pid_file.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module Djinn
|
2
|
+
# pid files are what bind your Djinn to the material plane
|
2
3
|
class PidFile
|
3
4
|
|
4
5
|
attr_reader :file
|
@@ -19,7 +20,7 @@ module Djinn
|
|
19
20
|
File.open(@file, "w") { |f| f.write($$) }
|
20
21
|
end
|
21
22
|
|
22
|
-
def ensure_empty
|
23
|
+
def ensure_empty(msg = nil)
|
23
24
|
if self.pid
|
24
25
|
$stdout.puts msg if msg
|
25
26
|
exit 1
|
data/lib/djinn/rails.rb
CHANGED
data/lib/djinn/tonic.rb
CHANGED
@@ -1,24 +1,20 @@
|
|
1
1
|
module Djinn
|
2
|
+
# This play on words kills me everytime. I'm that lame.
|
2
3
|
module Tonic
|
3
4
|
|
5
|
+
# Send your Djinn off to frolic in the ether
|
4
6
|
def daemonize(logfile, pidfile, &block)
|
5
|
-
|
6
|
-
pidfile.ensure_empty! "ERROR: It looks like I'm already running. Not starting."
|
7
|
-
|
7
|
+
pidfile.ensure_empty("It looks like I'm already running. Not starting.")
|
8
8
|
puts "Djinn is leaving process #{$$}"
|
9
|
-
|
10
|
-
srand #
|
11
|
-
|
9
|
+
|
10
|
+
srand # split rand streams between spawning and daemonized process
|
11
|
+
|
12
12
|
fork do
|
13
|
-
|
14
13
|
puts "Daemonizing on process #{$$}"
|
15
14
|
# puts system("ps aux | grep #{$$}")
|
16
15
|
|
17
|
-
#
|
18
|
-
#
|
19
|
-
|
20
|
-
#Dir.chdir "/" # Release old working directory
|
21
|
-
File.umask 0000 # Ensure sensible umask
|
16
|
+
#Dir.chdir "/" # release old working directory
|
17
|
+
File.umask 0000 # ensure sensible umask
|
22
18
|
|
23
19
|
puts 'Making sure all file descriptors are closed'
|
24
20
|
ObjectSpace.each_object(IO) do |io|
|
@@ -30,16 +26,14 @@ module Djinn
|
|
30
26
|
end
|
31
27
|
end
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
puts 'Detaching from the controlling terminal'
|
29
|
+
pidfile.create # write PID file
|
30
|
+
|
31
|
+
# detach from controlling terminal
|
37
32
|
unless sess_id = Process.setsid
|
38
|
-
raise '
|
33
|
+
raise 'Cannot detach from controlling terminal'
|
39
34
|
end
|
40
35
|
|
41
|
-
#
|
42
|
-
puts "Logging to: #{logfile}"
|
36
|
+
# redirect IO
|
43
37
|
STDIN.reopen('/dev/null')
|
44
38
|
STDOUT.reopen(logfile, 'a')
|
45
39
|
STDERR.reopen(STDOUT)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: djinn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.9
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Craig Paterson
|