djinn 0.0.9 → 0.1.0
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/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
|