tootsie 0.9.3 → 0.9.4
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.md +4 -2
- data/bin/tootsie +1 -69
- data/lib/tootsie.rb +1 -1
- data/lib/tootsie/application.rb +8 -1
- data/lib/tootsie/configuration.rb +5 -1
- data/lib/tootsie/runner.rb +118 -0
- data/lib/tootsie/version.rb +1 -1
- metadata +119 -206
- data/config/development-sample.yml +0 -4
- data/lib/tootsie/daemon.rb +0 -282
data/README.md
CHANGED
@@ -180,7 +180,6 @@ Example S3 URLs:
|
|
180
180
|
Current limitations
|
181
181
|
===================
|
182
182
|
|
183
|
-
* Daemon supports only one task manager thread at a time.
|
184
183
|
* Transcoding options are very basic.
|
185
184
|
* No client access control; anyone can submit jobs.
|
186
185
|
|
@@ -216,8 +215,11 @@ Create a configuration, eg. `tootsie.conf`:
|
|
216
215
|
aws_access_key_id: <your Amazon key>
|
217
216
|
aws_secret_access_key: <your Amazon secret>
|
218
217
|
sqs_queue_name: tootsie
|
218
|
+
pid_path: <where to write pid file>
|
219
|
+
log_path: <where to write log file>
|
220
|
+
worker_count: <number of workers>
|
219
221
|
|
220
|
-
Start the task manager with `tootsie -c tootsie.conf
|
222
|
+
Start the task manager with `tootsie -c tootsie.conf`.
|
221
223
|
|
222
224
|
To run the web service, you will need a Rack-compatible web server, such as Unicorn or Thin. To start with Thin on port 9090:
|
223
225
|
|
data/bin/tootsie
CHANGED
@@ -3,72 +3,4 @@
|
|
3
3
|
$:.unshift(File.expand_path('../../lib', __FILE__))
|
4
4
|
require 'tootsie'
|
5
5
|
|
6
|
-
|
7
|
-
config_path = nil
|
8
|
-
log_target = 'syslog'
|
9
|
-
|
10
|
-
ARGV.options do |opts|
|
11
|
-
opts.banner = "Usage: #{File.basename($0)} [OPTIONS] [start | stop | restart | status]"
|
12
|
-
opts.separator ""
|
13
|
-
opts.on("-n", "--num-workers=WORKERS", Integer,
|
14
|
-
"Specify number of workers to fork (defaults to #{num_workers}.") do |value|
|
15
|
-
num_workers = [1, value.to_i].max
|
16
|
-
end
|
17
|
-
opts.on("-c", "--config=PATH", String,
|
18
|
-
"Specify configuration path.") do |value|
|
19
|
-
config_path = value
|
20
|
-
end
|
21
|
-
opts.on("-l TARGET", "--logger TARGET", String,
|
22
|
-
"Log to TARGET, which is either a file name or 'syslog'.") do |value|
|
23
|
-
log_target = value
|
24
|
-
end
|
25
|
-
opts.on("-h", "--help", "Show this help message.") do
|
26
|
-
puts opts
|
27
|
-
exit
|
28
|
-
end
|
29
|
-
opts.parse!
|
30
|
-
if ARGV.empty?
|
31
|
-
puts "Nothing to do. Run with -h for help."
|
32
|
-
exit
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
unless config_path
|
37
|
-
abort 'Configuration file not specified.'
|
38
|
-
end
|
39
|
-
config_path = File.expand_path(config_path)
|
40
|
-
|
41
|
-
case log_target
|
42
|
-
when 'syslog'
|
43
|
-
logger = SyslogLogger.new('tootsie')
|
44
|
-
else
|
45
|
-
logger = Logger.new(log_target)
|
46
|
-
end
|
47
|
-
|
48
|
-
controller = Tootsie::Daemon.new(
|
49
|
-
:root => File.join(File.dirname(__FILE__), "/.."),
|
50
|
-
:pid_file => File.join(File.dirname(__FILE__), "/../tmp/task_manager.pid"),
|
51
|
-
:logger => logger)
|
52
|
-
|
53
|
-
spawner = Spawner.new(:num_children => num_workers, :logger => controller.logger)
|
54
|
-
|
55
|
-
controller.on_spawn do
|
56
|
-
$0 = "tootsie: master"
|
57
|
-
spawner.on_spawn do
|
58
|
-
$0 = "tootsie: worker"
|
59
|
-
Signal.trap('TERM') do
|
60
|
-
exit(2)
|
61
|
-
end
|
62
|
-
app = Tootsie::Application.new(:logger => controller.logger)
|
63
|
-
app.configure!(config_path)
|
64
|
-
begin
|
65
|
-
app.task_manager.run!
|
66
|
-
rescue SystemExit, Interrupt
|
67
|
-
end
|
68
|
-
end
|
69
|
-
spawner.run
|
70
|
-
end
|
71
|
-
controller.on_terminate do
|
72
|
-
spawner.terminate
|
73
|
-
end
|
74
|
-
controller.control(ARGV)
|
6
|
+
Tootsie::Runner.new.run!(ARGV)
|
data/lib/tootsie.rb
CHANGED
@@ -8,7 +8,6 @@ require 'tootsie/application'
|
|
8
8
|
require 'tootsie/client'
|
9
9
|
require 'tootsie/configuration'
|
10
10
|
require 'tootsie/command_runner'
|
11
|
-
require 'tootsie/daemon'
|
12
11
|
require 'tootsie/spawner'
|
13
12
|
require 'tootsie/ffmpeg_adapter'
|
14
13
|
require 'tootsie/image_metadata_extractor'
|
@@ -23,3 +22,4 @@ require 'tootsie/processors/image_processor'
|
|
23
22
|
require 'tootsie/queues/sqs_queue'
|
24
23
|
require 'tootsie/queues/file_system_queue'
|
25
24
|
require 'tootsie/s3_utilities'
|
25
|
+
require 'tootsie/runner'
|
data/lib/tootsie/application.rb
CHANGED
@@ -4,12 +4,19 @@ module Tootsie
|
|
4
4
|
|
5
5
|
def initialize(options = {})
|
6
6
|
@@instance = self
|
7
|
-
@logger = options[:logger] || Logger.new($stderr)
|
8
7
|
@configuration = Configuration.new
|
9
8
|
end
|
10
9
|
|
11
10
|
def configure!(config_path)
|
12
11
|
@configuration.load_from_file(config_path)
|
12
|
+
case @configuration.log_path
|
13
|
+
when 'syslog'
|
14
|
+
@logger = SyslogLogger.new('tootsie')
|
15
|
+
when String
|
16
|
+
@logger = Logger.new(@configuration.log_path)
|
17
|
+
else
|
18
|
+
@logger = Logger.new($stderr)
|
19
|
+
end
|
13
20
|
@queue = Tootsie::SqsQueue.new(@configuration.sqs_queue_name, sqs_service)
|
14
21
|
@task_manager = TaskManager.new(@queue)
|
15
22
|
end
|
@@ -4,13 +4,14 @@ module Tootsie
|
|
4
4
|
|
5
5
|
def initialize
|
6
6
|
@ffmpeg_thread_count = 1
|
7
|
+
@worker_count = 4
|
7
8
|
@sqs_queue_name = 'tootsie'
|
8
9
|
end
|
9
10
|
|
10
11
|
def load_from_file(file_name)
|
11
12
|
config = (YAML.load(File.read(file_name)) || {}).with_indifferent_access
|
12
13
|
[:aws_access_key_id, :aws_secret_access_key, :ffmpeg_thread_count,
|
13
|
-
:sqs_queue_name].each do |key|
|
14
|
+
:sqs_queue_name, :worker_count, :pid_path, :log_path].each do |key|
|
14
15
|
if config.include?(key)
|
15
16
|
value = config[key]
|
16
17
|
value = $1.to_i if value =~ /\A\s*(\d+)\s*\z/
|
@@ -23,6 +24,9 @@ module Tootsie
|
|
23
24
|
attr_accessor :aws_secret_access_key
|
24
25
|
attr_accessor :ffmpeg_thread_count
|
25
26
|
attr_accessor :sqs_queue_name
|
27
|
+
attr_accessor :pid_path
|
28
|
+
attr_accessor :log_path
|
29
|
+
attr_accessor :worker_count
|
26
30
|
|
27
31
|
end
|
28
32
|
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module Tootsie
|
2
|
+
|
3
|
+
# Runs the daemon from the command line.
|
4
|
+
class Runner
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@run_as_daemon = false
|
8
|
+
@config_path = '/etc/tootsie/tootsie.conf'
|
9
|
+
@app = Application.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def run!(arguments = [])
|
13
|
+
OptionParser.new do |opts|
|
14
|
+
opts.banner = "Usage: #{File.basename($0)} [OPTIONS]"
|
15
|
+
opts.separator ""
|
16
|
+
opts.on("-d", "--daemon", 'Run as daemon') do
|
17
|
+
@run_as_daemon = true
|
18
|
+
end
|
19
|
+
opts.on("-p PATH", "--pid", "Store pid in PATH (defaults to #{@pid_path})") do |value|
|
20
|
+
@pid_path = File.expand_path(value)
|
21
|
+
end
|
22
|
+
opts.on("-c FILE", "--config FILE", "Read configuration from FILE (defaults to #{@config_path})") do |value|
|
23
|
+
@config_path = File.expand_path(value)
|
24
|
+
end
|
25
|
+
opts.on("-h", "--help", "Show this help.") do
|
26
|
+
puts opts
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
opts.parse!(arguments)
|
30
|
+
end
|
31
|
+
|
32
|
+
@app.configure!(@config_path)
|
33
|
+
|
34
|
+
if @run_as_daemon
|
35
|
+
daemonize!
|
36
|
+
else
|
37
|
+
execute!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def execute!
|
44
|
+
with_pid do
|
45
|
+
@spawner = Spawner.new(
|
46
|
+
:num_children => @app.configuration.worker_count,
|
47
|
+
:logger => logger)
|
48
|
+
@spawner.on_spawn do
|
49
|
+
$0 = "tootsie: worker"
|
50
|
+
Signal.trap('TERM') do
|
51
|
+
exit(2)
|
52
|
+
end
|
53
|
+
with_lifecycle_logging("Worker [#{Process.pid}]") do
|
54
|
+
@app.task_manager.run!
|
55
|
+
end
|
56
|
+
end
|
57
|
+
with_lifecycle_logging('Main process') do
|
58
|
+
@spawner.run
|
59
|
+
end
|
60
|
+
@spawner.terminate
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def daemonize!(&block)
|
65
|
+
return Process.fork {
|
66
|
+
logger = @app.logger
|
67
|
+
|
68
|
+
Process.setsid
|
69
|
+
0.upto(255) do |n|
|
70
|
+
File.for_fd(n, "r").close rescue nil
|
71
|
+
end
|
72
|
+
|
73
|
+
File.umask(27)
|
74
|
+
Dir.chdir('/')
|
75
|
+
$stdin.reopen("/dev/null", 'r')
|
76
|
+
$stdout.reopen("/dev/null", 'w')
|
77
|
+
$stderr.reopen("/dev/null", 'w')
|
78
|
+
|
79
|
+
Signal.trap("HUP") do
|
80
|
+
logger.debug("Ignoring SIGHUP")
|
81
|
+
end
|
82
|
+
|
83
|
+
execute!
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def with_pid(&block)
|
88
|
+
path = @pid_path
|
89
|
+
path ||= @app.configuration.pid_path
|
90
|
+
path ||= '/var/run/tootsie.pid'
|
91
|
+
|
92
|
+
File.open(path, 'w') do |file|
|
93
|
+
file << Process.pid
|
94
|
+
end
|
95
|
+
begin
|
96
|
+
yield
|
97
|
+
ensure
|
98
|
+
File.delete(path) rescue nil
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def with_lifecycle_logging(prefix, &block)
|
103
|
+
logger.info("#{prefix} starting")
|
104
|
+
yield
|
105
|
+
rescue SystemExit, Interrupt, SignalException
|
106
|
+
logger.info("#{prefix} signaled")
|
107
|
+
rescue Exception => e
|
108
|
+
logger.error("#{prefix} failed with exception #{e.class}: #{e}")
|
109
|
+
exit(1)
|
110
|
+
end
|
111
|
+
|
112
|
+
def logger
|
113
|
+
@app.logger
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
data/lib/tootsie/version.rb
CHANGED
metadata
CHANGED
@@ -1,266 +1,189 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: tootsie
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.4
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 9
|
9
|
-
- 3
|
10
|
-
version: 0.9.3
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Alexander Staubo
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-01-20 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: json
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70337010813360 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
18
|
+
requirements:
|
26
19
|
- - ~>
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
hash: 11
|
29
|
-
segments:
|
30
|
-
- 1
|
31
|
-
- 4
|
32
|
-
- 6
|
20
|
+
- !ruby/object:Gem::Version
|
33
21
|
version: 1.4.6
|
34
22
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: sinatra
|
38
23
|
prerelease: false
|
39
|
-
|
24
|
+
version_requirements: *70337010813360
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sinatra
|
27
|
+
requirement: &70337010812840 !ruby/object:Gem::Requirement
|
40
28
|
none: false
|
41
|
-
requirements:
|
29
|
+
requirements:
|
42
30
|
- - ~>
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
|
45
|
-
segments:
|
46
|
-
- 1
|
47
|
-
- 0
|
48
|
-
version: "1.0"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.0'
|
49
33
|
type: :runtime
|
50
|
-
version_requirements: *id002
|
51
|
-
- !ruby/object:Gem::Dependency
|
52
|
-
name: activesupport
|
53
34
|
prerelease: false
|
54
|
-
|
35
|
+
version_requirements: *70337010812840
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: activesupport
|
38
|
+
requirement: &70337010812360 !ruby/object:Gem::Requirement
|
55
39
|
none: false
|
56
|
-
requirements:
|
40
|
+
requirements:
|
57
41
|
- - ~>
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
hash: 7
|
60
|
-
segments:
|
61
|
-
- 3
|
62
|
-
- 0
|
63
|
-
- 0
|
42
|
+
- !ruby/object:Gem::Version
|
64
43
|
version: 3.0.0
|
65
44
|
type: :runtime
|
66
|
-
version_requirements: *id003
|
67
|
-
- !ruby/object:Gem::Dependency
|
68
|
-
name: httpclient
|
69
45
|
prerelease: false
|
70
|
-
|
46
|
+
version_requirements: *70337010812360
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: httpclient
|
49
|
+
requirement: &70337010811880 !ruby/object:Gem::Requirement
|
71
50
|
none: false
|
72
|
-
requirements:
|
51
|
+
requirements:
|
73
52
|
- - ~>
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
hash: 5
|
76
|
-
segments:
|
77
|
-
- 2
|
78
|
-
- 2
|
79
|
-
- 1
|
53
|
+
- !ruby/object:Gem::Version
|
80
54
|
version: 2.2.1
|
81
55
|
type: :runtime
|
82
|
-
version_requirements: *id004
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: builder
|
85
56
|
prerelease: false
|
86
|
-
|
57
|
+
version_requirements: *70337010811880
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: builder
|
60
|
+
requirement: &70337010811400 !ruby/object:Gem::Requirement
|
87
61
|
none: false
|
88
|
-
requirements:
|
62
|
+
requirements:
|
89
63
|
- - ~>
|
90
|
-
- !ruby/object:Gem::Version
|
91
|
-
hash: 15
|
92
|
-
segments:
|
93
|
-
- 2
|
94
|
-
- 1
|
95
|
-
- 2
|
64
|
+
- !ruby/object:Gem::Version
|
96
65
|
version: 2.1.2
|
97
66
|
type: :runtime
|
98
|
-
version_requirements: *id005
|
99
|
-
- !ruby/object:Gem::Dependency
|
100
|
-
name: mime-types
|
101
67
|
prerelease: false
|
102
|
-
|
68
|
+
version_requirements: *70337010811400
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mime-types
|
71
|
+
requirement: &70337010810920 !ruby/object:Gem::Requirement
|
103
72
|
none: false
|
104
|
-
requirements:
|
73
|
+
requirements:
|
105
74
|
- - ~>
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
|
108
|
-
segments:
|
109
|
-
- 1
|
110
|
-
- 16
|
111
|
-
version: "1.16"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '1.16'
|
112
77
|
type: :runtime
|
113
|
-
version_requirements: *id006
|
114
|
-
- !ruby/object:Gem::Dependency
|
115
|
-
name: xml-simple
|
116
78
|
prerelease: false
|
117
|
-
|
79
|
+
version_requirements: *70337010810920
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: xml-simple
|
82
|
+
requirement: &70337010810440 !ruby/object:Gem::Requirement
|
118
83
|
none: false
|
119
|
-
requirements:
|
84
|
+
requirements:
|
120
85
|
- - ~>
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
hash: 15
|
123
|
-
segments:
|
124
|
-
- 1
|
125
|
-
- 0
|
126
|
-
- 12
|
86
|
+
- !ruby/object:Gem::Version
|
127
87
|
version: 1.0.12
|
128
88
|
type: :runtime
|
129
|
-
version_requirements: *id007
|
130
|
-
- !ruby/object:Gem::Dependency
|
131
|
-
name: thin
|
132
89
|
prerelease: false
|
133
|
-
|
90
|
+
version_requirements: *70337010810440
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: thin
|
93
|
+
requirement: &70337010809960 !ruby/object:Gem::Requirement
|
134
94
|
none: false
|
135
|
-
requirements:
|
95
|
+
requirements:
|
136
96
|
- - ~>
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
hash: 17
|
139
|
-
segments:
|
140
|
-
- 1
|
141
|
-
- 2
|
142
|
-
- 7
|
97
|
+
- !ruby/object:Gem::Version
|
143
98
|
version: 1.2.7
|
144
99
|
type: :runtime
|
145
|
-
version_requirements: *id008
|
146
|
-
- !ruby/object:Gem::Dependency
|
147
|
-
name: s3
|
148
100
|
prerelease: false
|
149
|
-
|
101
|
+
version_requirements: *70337010809960
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: s3
|
104
|
+
requirement: &70337010809480 !ruby/object:Gem::Requirement
|
150
105
|
none: false
|
151
|
-
requirements:
|
106
|
+
requirements:
|
152
107
|
- - ~>
|
153
|
-
- !ruby/object:Gem::Version
|
154
|
-
hash: 29
|
155
|
-
segments:
|
156
|
-
- 0
|
157
|
-
- 3
|
158
|
-
- 7
|
108
|
+
- !ruby/object:Gem::Version
|
159
109
|
version: 0.3.7
|
160
110
|
type: :runtime
|
161
|
-
version_requirements: *id009
|
162
|
-
- !ruby/object:Gem::Dependency
|
163
|
-
name: sqs
|
164
111
|
prerelease: false
|
165
|
-
|
112
|
+
version_requirements: *70337010809480
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: sqs
|
115
|
+
requirement: &70337010809000 !ruby/object:Gem::Requirement
|
166
116
|
none: false
|
167
|
-
requirements:
|
117
|
+
requirements:
|
168
118
|
- - ~>
|
169
|
-
- !ruby/object:Gem::Version
|
170
|
-
hash: 31
|
171
|
-
segments:
|
172
|
-
- 0
|
173
|
-
- 1
|
174
|
-
- 2
|
119
|
+
- !ruby/object:Gem::Version
|
175
120
|
version: 0.1.2
|
176
121
|
type: :runtime
|
177
|
-
version_requirements: *id010
|
178
|
-
- !ruby/object:Gem::Dependency
|
179
|
-
name: unicorn
|
180
122
|
prerelease: false
|
181
|
-
|
123
|
+
version_requirements: *70337010809000
|
124
|
+
- !ruby/object:Gem::Dependency
|
125
|
+
name: unicorn
|
126
|
+
requirement: &70337010808520 !ruby/object:Gem::Requirement
|
182
127
|
none: false
|
183
|
-
requirements:
|
128
|
+
requirements:
|
184
129
|
- - ~>
|
185
|
-
- !ruby/object:Gem::Version
|
186
|
-
hash: 57
|
187
|
-
segments:
|
188
|
-
- 4
|
189
|
-
- 1
|
190
|
-
- 1
|
130
|
+
- !ruby/object:Gem::Version
|
191
131
|
version: 4.1.1
|
192
132
|
type: :runtime
|
193
|
-
version_requirements: *id011
|
194
|
-
- !ruby/object:Gem::Dependency
|
195
|
-
name: i18n
|
196
133
|
prerelease: false
|
197
|
-
|
134
|
+
version_requirements: *70337010808520
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: i18n
|
137
|
+
requirement: &70337010808040 !ruby/object:Gem::Requirement
|
198
138
|
none: false
|
199
|
-
requirements:
|
200
|
-
- -
|
201
|
-
- !ruby/object:Gem::Version
|
202
|
-
hash: 11
|
203
|
-
segments:
|
204
|
-
- 0
|
205
|
-
- 4
|
206
|
-
- 2
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
207
142
|
version: 0.4.2
|
208
143
|
type: :runtime
|
209
|
-
version_requirements: *id012
|
210
|
-
- !ruby/object:Gem::Dependency
|
211
|
-
name: scashin133-syslog_logger
|
212
144
|
prerelease: false
|
213
|
-
|
145
|
+
version_requirements: *70337010808040
|
146
|
+
- !ruby/object:Gem::Dependency
|
147
|
+
name: scashin133-syslog_logger
|
148
|
+
requirement: &70337010807560 !ruby/object:Gem::Requirement
|
214
149
|
none: false
|
215
|
-
requirements:
|
150
|
+
requirements:
|
216
151
|
- - ~>
|
217
|
-
- !ruby/object:Gem::Version
|
218
|
-
hash: 13
|
219
|
-
segments:
|
220
|
-
- 1
|
221
|
-
- 7
|
222
|
-
- 3
|
152
|
+
- !ruby/object:Gem::Version
|
223
153
|
version: 1.7.3
|
224
154
|
type: :runtime
|
225
|
-
version_requirements: *id013
|
226
|
-
- !ruby/object:Gem::Dependency
|
227
|
-
name: rspec
|
228
155
|
prerelease: false
|
229
|
-
|
156
|
+
version_requirements: *70337010807560
|
157
|
+
- !ruby/object:Gem::Dependency
|
158
|
+
name: rspec
|
159
|
+
requirement: &70337010807180 !ruby/object:Gem::Requirement
|
230
160
|
none: false
|
231
|
-
requirements:
|
232
|
-
- -
|
233
|
-
- !ruby/object:Gem::Version
|
234
|
-
|
235
|
-
segments:
|
236
|
-
- 0
|
237
|
-
version: "0"
|
161
|
+
requirements:
|
162
|
+
- - ! '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
238
165
|
type: :development
|
239
|
-
version_requirements: *id014
|
240
|
-
- !ruby/object:Gem::Dependency
|
241
|
-
name: rake
|
242
166
|
prerelease: false
|
243
|
-
|
167
|
+
version_requirements: *70337010807180
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: rake
|
170
|
+
requirement: &70337010806720 !ruby/object:Gem::Requirement
|
244
171
|
none: false
|
245
|
-
requirements:
|
246
|
-
- -
|
247
|
-
- !ruby/object:Gem::Version
|
248
|
-
|
249
|
-
segments:
|
250
|
-
- 0
|
251
|
-
version: "0"
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
252
176
|
type: :development
|
253
|
-
|
177
|
+
prerelease: false
|
178
|
+
version_requirements: *70337010806720
|
254
179
|
description: Tootsie is a simple audio/video/image transcoding/modification application.
|
255
|
-
email:
|
180
|
+
email:
|
256
181
|
- alex@origo.no
|
257
|
-
executables:
|
182
|
+
executables:
|
258
183
|
- tootsie
|
259
184
|
extensions: []
|
260
|
-
|
261
185
|
extra_rdoc_files: []
|
262
|
-
|
263
|
-
files:
|
186
|
+
files:
|
264
187
|
- .gitignore
|
265
188
|
- Gemfile
|
266
189
|
- License
|
@@ -269,13 +192,11 @@ files:
|
|
269
192
|
- Tootsie.gemspec
|
270
193
|
- bin/tootsie
|
271
194
|
- config.ru
|
272
|
-
- config/development-sample.yml
|
273
195
|
- lib/tootsie.rb
|
274
196
|
- lib/tootsie/application.rb
|
275
197
|
- lib/tootsie/client.rb
|
276
198
|
- lib/tootsie/command_runner.rb
|
277
199
|
- lib/tootsie/configuration.rb
|
278
|
-
- lib/tootsie/daemon.rb
|
279
200
|
- lib/tootsie/ffmpeg_adapter.rb
|
280
201
|
- lib/tootsie/image_metadata_extractor.rb
|
281
202
|
- lib/tootsie/input.rb
|
@@ -284,6 +205,7 @@ files:
|
|
284
205
|
- lib/tootsie/processors/video_processor.rb
|
285
206
|
- lib/tootsie/queues/file_system_queue.rb
|
286
207
|
- lib/tootsie/queues/sqs_queue.rb
|
208
|
+
- lib/tootsie/runner.rb
|
287
209
|
- lib/tootsie/s3_utilities.rb
|
288
210
|
- lib/tootsie/spawner.rb
|
289
211
|
- lib/tootsie/task_manager.rb
|
@@ -298,38 +220,29 @@ files:
|
|
298
220
|
- spec/tootsie/s3_utilities_spec.rb
|
299
221
|
homepage: http://github.com/alexstaubo/tootsie
|
300
222
|
licenses: []
|
301
|
-
|
302
223
|
post_install_message:
|
303
224
|
rdoc_options: []
|
304
|
-
|
305
|
-
require_paths:
|
225
|
+
require_paths:
|
306
226
|
- lib
|
307
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
227
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
308
228
|
none: false
|
309
|
-
requirements:
|
310
|
-
- -
|
311
|
-
- !ruby/object:Gem::Version
|
312
|
-
|
313
|
-
|
314
|
-
- 0
|
315
|
-
version: "0"
|
316
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
229
|
+
requirements:
|
230
|
+
- - ! '>='
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: '0'
|
233
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
317
234
|
none: false
|
318
|
-
requirements:
|
319
|
-
- -
|
320
|
-
- !ruby/object:Gem::Version
|
321
|
-
|
322
|
-
segments:
|
323
|
-
- 0
|
324
|
-
version: "0"
|
235
|
+
requirements:
|
236
|
+
- - ! '>='
|
237
|
+
- !ruby/object:Gem::Version
|
238
|
+
version: '0'
|
325
239
|
requirements: []
|
326
|
-
|
327
240
|
rubyforge_project: tootsie
|
328
241
|
rubygems_version: 1.8.6
|
329
242
|
signing_key:
|
330
243
|
specification_version: 3
|
331
244
|
summary: Tootsie is a simple audio/video/image transcoding/modification application.
|
332
|
-
test_files:
|
245
|
+
test_files:
|
333
246
|
- spec/spec_helper.rb
|
334
247
|
- spec/test_files/BF 0622 1820.tif
|
335
248
|
- spec/tootsie/command_runner_spec.rb
|
data/lib/tootsie/daemon.rb
DELETED
@@ -1,282 +0,0 @@
|
|
1
|
-
require "logger"
|
2
|
-
require "fileutils"
|
3
|
-
require 'optparse'
|
4
|
-
|
5
|
-
module Tootsie
|
6
|
-
|
7
|
-
class DaemonError < Exception; end
|
8
|
-
class DaemonAlreadyRunning < DaemonError; end
|
9
|
-
class DaemonNotRunning < DaemonError; end
|
10
|
-
class DaemonTerminationFailed < DaemonError; end
|
11
|
-
class DaemonNotConfigured < DaemonError; end
|
12
|
-
class DaemonStartFailed < DaemonError; end
|
13
|
-
|
14
|
-
# Daemon controller class that encapsulates a running daemon and a remote interface to it.
|
15
|
-
class Daemon
|
16
|
-
|
17
|
-
# Initializes the daemon controller.
|
18
|
-
def initialize(options = {})
|
19
|
-
@root = options[:root] || Dir.pwd
|
20
|
-
@pid_file = options[:pid_file]
|
21
|
-
@logger = options[:logger] || Logger.new('/dev/null')
|
22
|
-
@on_spawn = nil
|
23
|
-
end
|
24
|
-
|
25
|
-
# Specifies a block to execute to run the actual daemon. Each call overrides the previous one.
|
26
|
-
def on_spawn(&block)
|
27
|
-
@on_spawn = block
|
28
|
-
end
|
29
|
-
|
30
|
-
# Specifies a block to execute to termiantion. Each call overrides the previous one.
|
31
|
-
def on_terminate(&block)
|
32
|
-
@on_terminate = block
|
33
|
-
end
|
34
|
-
|
35
|
-
# Control the daemon through command-line arguments.
|
36
|
-
def control(args, title = nil)
|
37
|
-
$stderr.sync = true
|
38
|
-
title ||= File.basename($0)
|
39
|
-
command = args.shift
|
40
|
-
control_with_command(command, args, title)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Control the daemon through a specific command.
|
44
|
-
def control_with_command(command, args, title = nil)
|
45
|
-
case command
|
46
|
-
when "start"
|
47
|
-
$stderr << "Starting #{title}: "
|
48
|
-
handle_errors do
|
49
|
-
start
|
50
|
-
$stderr << "started\n"
|
51
|
-
end
|
52
|
-
when "stop"
|
53
|
-
$stderr << "Stopping #{title}: "
|
54
|
-
options = {}
|
55
|
-
handle_errors do
|
56
|
-
stop({:signal => "TERM"}.merge(options))
|
57
|
-
$stderr << "stopped\n"
|
58
|
-
end
|
59
|
-
when "restart"
|
60
|
-
$stderr << "Restarting #{title}: "
|
61
|
-
handle_errors do
|
62
|
-
restart
|
63
|
-
$stderr << "restarted\n"
|
64
|
-
end
|
65
|
-
when "status"
|
66
|
-
if running?
|
67
|
-
$stderr << "#{title} is running\n"
|
68
|
-
else
|
69
|
-
$stderr << "#{title} is not running\n"
|
70
|
-
end
|
71
|
-
else
|
72
|
-
if command
|
73
|
-
$stderr << "#{File.basename($0)}: Invalid command #{command}\n"
|
74
|
-
else
|
75
|
-
puts "Usage: #{File.basename($0)} [start | stop | restart | status]"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# Starts daemon.
|
81
|
-
def start
|
82
|
-
raise DaemonNotConfigured, "Daemon not configured" unless @on_spawn
|
83
|
-
FileUtils.mkdir_p(File.dirname(@pid_file)) rescue nil
|
84
|
-
pid = self.pid
|
85
|
-
if pid
|
86
|
-
if pid_running?(pid)
|
87
|
-
raise DaemonAlreadyRunning, "Process is already running with pid #{pid}"
|
88
|
-
end
|
89
|
-
end
|
90
|
-
File.delete(@pid_file) rescue nil
|
91
|
-
child_pid = Process.fork
|
92
|
-
if child_pid
|
93
|
-
sleep(1)
|
94
|
-
unless running?
|
95
|
-
pid = self.pid
|
96
|
-
if pid == child_pid
|
97
|
-
raise DaemonStartFailed, "Daemon started, but failed prematurely"
|
98
|
-
else
|
99
|
-
raise DaemonStartFailed, "Daemon failed to start for some unknown reason"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
return
|
103
|
-
end
|
104
|
-
class << logger
|
105
|
-
def format_message(severity, timestamp, progname, msg)
|
106
|
-
"[#{timestamp}] #{msg}\n"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
logger.info("Starting")
|
110
|
-
begin
|
111
|
-
Process.setsid
|
112
|
-
0.upto(255) do |n|
|
113
|
-
File.for_fd(n, "r").close rescue nil
|
114
|
-
end
|
115
|
-
File.umask(27)
|
116
|
-
Dir.chdir(@root)
|
117
|
-
$stdin = File.open("/dev/null", File::RDWR)
|
118
|
-
$stdout = File.open("/dev/null", File::RDWR)
|
119
|
-
$stderr = File.open("/dev/null", File::RDWR)
|
120
|
-
@pid = Process.pid
|
121
|
-
File.open(@pid_file, "w") do |file|
|
122
|
-
file << Process.pid
|
123
|
-
end
|
124
|
-
Signal.trap("HUP") do
|
125
|
-
logger.debug("Ignoring SIGHUP")
|
126
|
-
end
|
127
|
-
Signal.trap("TERM") do
|
128
|
-
if $$ == @pid
|
129
|
-
logger.info("Terminating (#{$$})")
|
130
|
-
@on_terminate.call if @on_terminate
|
131
|
-
File.delete(@pid_file) rescue nil
|
132
|
-
else
|
133
|
-
# Was sent to a child
|
134
|
-
end
|
135
|
-
exit(0)
|
136
|
-
end
|
137
|
-
@on_spawn.call
|
138
|
-
exit(0)
|
139
|
-
rescue SystemExit
|
140
|
-
# Do nothing
|
141
|
-
rescue Exception => e
|
142
|
-
message = "#{e.message}\n"
|
143
|
-
message << e.backtrace.map { |line| "\tfrom #{line}\n" }.join
|
144
|
-
logger.error(message)
|
145
|
-
exit(1)
|
146
|
-
ensure
|
147
|
-
logger.close
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
# Stops daemon.
|
152
|
-
def stop(options = {})
|
153
|
-
stopped = false
|
154
|
-
found = false
|
155
|
-
pid = self.pid
|
156
|
-
if pid
|
157
|
-
# Send TERM to process
|
158
|
-
begin
|
159
|
-
Process.kill(options[:signal] || "TERM", pid)
|
160
|
-
rescue Errno::ESRCH
|
161
|
-
stopped = true
|
162
|
-
rescue Exception => e
|
163
|
-
raise DaemonTerminationFailed, "Could not stop process #{pid}: #{e.message}"
|
164
|
-
end
|
165
|
-
unless stopped
|
166
|
-
# Process was signaled, now wait for it to die
|
167
|
-
found = true
|
168
|
-
30.times do
|
169
|
-
begin
|
170
|
-
if not pid_running?(pid)
|
171
|
-
stopped = true
|
172
|
-
break
|
173
|
-
end
|
174
|
-
sleep(1)
|
175
|
-
rescue Exception => e
|
176
|
-
raise DaemonTerminationFailed, "Could not stop process #{pid}: #{e.message}"
|
177
|
-
end
|
178
|
-
end
|
179
|
-
if found and not stopped
|
180
|
-
# Process still running after wait, force kill and wait
|
181
|
-
begin
|
182
|
-
Process.kill("KILL", pid)
|
183
|
-
rescue Errno::ESRCH
|
184
|
-
stopped = true
|
185
|
-
end
|
186
|
-
30.times do
|
187
|
-
begin
|
188
|
-
if not pid_running?(pid)
|
189
|
-
stopped = true
|
190
|
-
break
|
191
|
-
end
|
192
|
-
sleep(1)
|
193
|
-
rescue Exception => e
|
194
|
-
raise DaemonTerminationFailed, "Could not stop process #{pid}: #{e.message}"
|
195
|
-
end
|
196
|
-
end
|
197
|
-
if not stopped
|
198
|
-
raise DaemonTerminationFailed, "Timeout attempting to stop process #{pid}"
|
199
|
-
end
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
unless found
|
204
|
-
raise DaemonNotRunning, "Process is not running"
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
# Restarts daemon.
|
209
|
-
def restart
|
210
|
-
if running?
|
211
|
-
begin
|
212
|
-
stop
|
213
|
-
rescue DaemonNotRunning
|
214
|
-
# Ignore
|
215
|
-
end
|
216
|
-
end
|
217
|
-
start
|
218
|
-
end
|
219
|
-
|
220
|
-
# Is the daemon running?
|
221
|
-
def running?
|
222
|
-
!pid.nil?
|
223
|
-
end
|
224
|
-
|
225
|
-
# Returns the daemon pid.
|
226
|
-
def pid
|
227
|
-
pid = nil
|
228
|
-
maybe_pid = File.read(@pid_file) rescue nil
|
229
|
-
if maybe_pid =~ /([0-9]+)/
|
230
|
-
maybe_pid = $1.to_i
|
231
|
-
begin
|
232
|
-
Process.kill(0, maybe_pid)
|
233
|
-
rescue Errno::ESRCH
|
234
|
-
else
|
235
|
-
pid = maybe_pid
|
236
|
-
end
|
237
|
-
end
|
238
|
-
pid
|
239
|
-
end
|
240
|
-
|
241
|
-
# Signals the daemon.
|
242
|
-
def signal(signal)
|
243
|
-
pid = self.pid
|
244
|
-
if pid
|
245
|
-
Process.kill(signal, pid)
|
246
|
-
else
|
247
|
-
raise DaemonNotRunning, "Process is not running"
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
attr_reader :root
|
252
|
-
attr_reader :pid_file
|
253
|
-
attr_reader :logger
|
254
|
-
|
255
|
-
private
|
256
|
-
|
257
|
-
def pid_running?(pid)
|
258
|
-
begin
|
259
|
-
Process.kill(0, pid)
|
260
|
-
rescue Errno::ESRCH
|
261
|
-
return false
|
262
|
-
end
|
263
|
-
return true
|
264
|
-
end
|
265
|
-
|
266
|
-
def handle_errors(&block)
|
267
|
-
begin
|
268
|
-
yield
|
269
|
-
rescue DaemonError => e
|
270
|
-
$stderr << "#{e.message}\n"
|
271
|
-
if e.is_a?(DaemonAlreadyRunning) or e.is_a?(DaemonNotRunning)
|
272
|
-
exit_code = 0
|
273
|
-
else
|
274
|
-
exit_code = 1
|
275
|
-
end
|
276
|
-
exit(exit_code)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
end
|
281
|
-
|
282
|
-
end
|