gina-conveyor 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +49 -0
- data/LICENSE +25 -0
- data/README.md +24 -0
- data/Rakefile +2 -0
- data/bin/conveyor +4 -0
- data/conveyor.gemspec +30 -0
- data/lib/conveyor/belt.rb +59 -0
- data/lib/conveyor/foreman.rb +182 -0
- data/lib/conveyor/input/commands.rb +21 -0
- data/lib/conveyor/input/console.rb +39 -0
- data/lib/conveyor/input.rb +12 -0
- data/lib/conveyor/job_state.rb +2 -0
- data/lib/conveyor/output/channel.rb +22 -0
- data/lib/conveyor/output/console.rb +39 -0
- data/lib/conveyor/output/email.rb +36 -0
- data/lib/conveyor/output/logfile.rb +38 -0
- data/lib/conveyor/output.rb +76 -0
- data/lib/conveyor/queue.rb +80 -0
- data/lib/conveyor/status.rb +29 -0
- data/lib/conveyor/version.rb +3 -0
- data/lib/conveyor/websocket.rb +37 -0
- data/lib/conveyor/worker.rb +120 -0
- data/lib/conveyor/workers/syntax.rb +127 -0
- data/lib/conveyor.rb +62 -0
- data/webviewer/.gitignore +15 -0
- data/webviewer/Gemfile +39 -0
- data/webviewer/Gemfile.lock +119 -0
- data/webviewer/README.rdoc +261 -0
- data/webviewer/Rakefile +7 -0
- data/webviewer/app/assets/images/rails.png +0 -0
- data/webviewer/app/assets/javascripts/application.js +16 -0
- data/webviewer/app/assets/javascripts/welcome.js.coffee +61 -0
- data/webviewer/app/assets/stylesheets/application.css.scss +6 -0
- data/webviewer/app/assets/stylesheets/welcome.css.scss +3 -0
- data/webviewer/app/controllers/application_controller.rb +3 -0
- data/webviewer/app/controllers/welcome_controller.rb +4 -0
- data/webviewer/app/helpers/application_helper.rb +2 -0
- data/webviewer/app/helpers/welcome_helper.rb +2 -0
- data/webviewer/app/mailers/.gitkeep +0 -0
- data/webviewer/app/models/.gitkeep +0 -0
- data/webviewer/app/views/layouts/application.html.haml +14 -0
- data/webviewer/app/views/welcome/index.html.haml +3 -0
- data/webviewer/config/application.rb +59 -0
- data/webviewer/config/boot.rb +6 -0
- data/webviewer/config/database.yml +25 -0
- data/webviewer/config/environment.rb +5 -0
- data/webviewer/config/environments/development.rb +37 -0
- data/webviewer/config/environments/production.rb +67 -0
- data/webviewer/config/environments/test.rb +37 -0
- data/webviewer/config/initializers/backtrace_silencers.rb +7 -0
- data/webviewer/config/initializers/inflections.rb +15 -0
- data/webviewer/config/initializers/mime_types.rb +5 -0
- data/webviewer/config/initializers/secret_token.rb +7 -0
- data/webviewer/config/initializers/session_store.rb +8 -0
- data/webviewer/config/initializers/wrap_parameters.rb +14 -0
- data/webviewer/config/locales/en.yml +5 -0
- data/webviewer/config/routes.rb +58 -0
- data/webviewer/config.ru +4 -0
- data/webviewer/db/seeds.rb +7 -0
- data/webviewer/doc/README_FOR_APP +2 -0
- data/webviewer/lib/assets/.gitkeep +0 -0
- data/webviewer/lib/tasks/.gitkeep +0 -0
- data/webviewer/log/.gitkeep +0 -0
- data/webviewer/public/404.html +26 -0
- data/webviewer/public/422.html +26 -0
- data/webviewer/public/500.html +25 -0
- data/webviewer/public/favicon.ico +0 -0
- data/webviewer/public/robots.txt +5 -0
- data/webviewer/script/rails +6 -0
- data/webviewer/test/fixtures/.gitkeep +0 -0
- data/webviewer/test/functional/.gitkeep +0 -0
- data/webviewer/test/functional/welcome_controller_test.rb +7 -0
- data/webviewer/test/integration/.gitkeep +0 -0
- data/webviewer/test/performance/browsing_test.rb +12 -0
- data/webviewer/test/test_helper.rb +13 -0
- data/webviewer/test/unit/.gitkeep +0 -0
- data/webviewer/test/unit/helpers/welcome_helper_test.rb +4 -0
- data/webviewer/vendor/assets/javascripts/.gitkeep +0 -0
- data/webviewer/vendor/assets/stylesheets/.gitkeep +0 -0
- data/webviewer/vendor/plugins/.gitkeep +0 -0
- data/worker-examples/barrow_webcam.worker.disabled +19 -0
- data/worker-examples/barrow_webcam.worker.example +16 -0
- data/worker-examples/conveyor.worker.example +5 -0
- data/worker-examples/devel.worker +17 -0
- metadata +260 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
gina-conveyor (0.0.2)
|
5
|
+
activemodel (~> 3.2.0)
|
6
|
+
activesupport (~> 3.2.0)
|
7
|
+
em-websocket (~> 0.3.6)
|
8
|
+
eventmachine (~> 0.12.10)
|
9
|
+
listen (~> 0.4.2)
|
10
|
+
rainbow (~> 1.1.4)
|
11
|
+
rb-readline (~> 0.4.2)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: http://rubygems.org/
|
15
|
+
specs:
|
16
|
+
activemodel (3.2.3)
|
17
|
+
activesupport (= 3.2.3)
|
18
|
+
builder (~> 3.0.0)
|
19
|
+
activesupport (3.2.3)
|
20
|
+
i18n (~> 0.6)
|
21
|
+
multi_json (~> 1.0)
|
22
|
+
addressable (2.2.8)
|
23
|
+
builder (3.0.0)
|
24
|
+
em-websocket (0.3.6)
|
25
|
+
addressable (>= 2.1.1)
|
26
|
+
eventmachine (>= 0.12.9)
|
27
|
+
eventmachine (0.12.10)
|
28
|
+
ffi (1.0.11)
|
29
|
+
i18n (0.6.0)
|
30
|
+
listen (0.4.2)
|
31
|
+
rb-fchange (~> 0.0.5)
|
32
|
+
rb-fsevent (~> 0.9.1)
|
33
|
+
rb-inotify (~> 0.8.8)
|
34
|
+
multi_json (1.3.5)
|
35
|
+
rainbow (1.1.4)
|
36
|
+
rake (0.9.2.2)
|
37
|
+
rb-fchange (0.0.5)
|
38
|
+
ffi
|
39
|
+
rb-fsevent (0.9.1)
|
40
|
+
rb-inotify (0.8.8)
|
41
|
+
ffi (>= 0.5.0)
|
42
|
+
rb-readline (0.4.2)
|
43
|
+
|
44
|
+
PLATFORMS
|
45
|
+
ruby
|
46
|
+
|
47
|
+
DEPENDENCIES
|
48
|
+
gina-conveyor!
|
49
|
+
rake
|
data/LICENSE
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Copyright (c) 2011 University of Alaska. All rights reserved.
|
2
|
+
|
3
|
+
Developed by: Will Fisher and Scott Macfarlane
|
4
|
+
Geographic Information Network of Alaska
|
5
|
+
University of Alaska Fairbanks
|
6
|
+
http://www.gina.alaska.edu
|
7
|
+
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
9
|
+
a copy of this software and associated documentation files (the
|
10
|
+
'Software'), to deal in the Software without restriction, including
|
11
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
12
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
13
|
+
permit persons to whom the Software is furnished to do so, subject to
|
14
|
+
the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be
|
17
|
+
included in all copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
20
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
21
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
22
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
23
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
24
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
25
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Conveyor
|
2
|
+
========
|
3
|
+
|
4
|
+
Start of a thought on some code to handle moving data around when it shows up on various systems
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
git clone https://github.com/gina-alaska/conveyor.git
|
10
|
+
cd conveyor
|
11
|
+
bundle install
|
12
|
+
|
13
|
+
Usage
|
14
|
+
-----
|
15
|
+
|
16
|
+
thor list # list available commands
|
17
|
+
thor help [command] # show help for the given command
|
18
|
+
thor belt list # list the currently active belts
|
19
|
+
thor worker watch # tell the workers to start watching directories!
|
20
|
+
|
21
|
+
License
|
22
|
+
-------
|
23
|
+
|
24
|
+
See LICENSE file for licensing and credits. Think BSD/MIT.
|
data/Rakefile
ADDED
data/bin/conveyor
ADDED
data/conveyor.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib/', __FILE__)
|
4
|
+
$:.unshift lib unless $:.include?(lib)
|
5
|
+
|
6
|
+
require 'conveyor/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |gem|
|
9
|
+
gem.authors = ["Will Fisher"]
|
10
|
+
gem.email = ["will@gina.alaska.edu"]
|
11
|
+
gem.summary = %q{GINA Data Conveyor}
|
12
|
+
gem.description = %q{Conveyor is used for shuffling data around}
|
13
|
+
gem.homepage = "http://github.com/gina-alaska/conveyor.git"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($\)
|
16
|
+
gem.executables = %w{conveyor}
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.name = "gina-conveyor"
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
gem.version = Conveyor::VERSION
|
21
|
+
|
22
|
+
gem.add_development_dependency('rake')
|
23
|
+
gem.add_dependency('activemodel', '~> 3.2.0')
|
24
|
+
gem.add_dependency('activesupport', '~> 3.2.0')
|
25
|
+
gem.add_dependency('listen', '~> 0.4.2')
|
26
|
+
gem.add_dependency('rainbow', '~> 1.1.4')
|
27
|
+
gem.add_dependency('rb-readline', '~> 0.4.2')
|
28
|
+
gem.add_dependency('eventmachine', '~> 0.12.10')
|
29
|
+
gem.add_dependency('em-websocket', '~> 0.3.6')
|
30
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Conveyor
|
2
|
+
# Does not persist, do not use any class variables
|
3
|
+
class Belt
|
4
|
+
SETTLE_TIME = 30
|
5
|
+
|
6
|
+
include Conveyor::Output
|
7
|
+
|
8
|
+
attr_reader :command_file
|
9
|
+
|
10
|
+
def initialize(watch_path, command_file)#, opts = {})
|
11
|
+
@work_dir = watch_path
|
12
|
+
@command_file = command_file
|
13
|
+
@queue = Conveyor::Queue.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def count
|
17
|
+
@queue.count
|
18
|
+
end
|
19
|
+
|
20
|
+
def name
|
21
|
+
File.basename(@command_file, '.worker')
|
22
|
+
end
|
23
|
+
|
24
|
+
def touch(files)
|
25
|
+
files.each do |f|
|
26
|
+
@queue.push(f)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def check
|
31
|
+
job = @queue.reserve
|
32
|
+
# puts job.inspect
|
33
|
+
if job && (Time.now - job[:updated_at]) > SETTLE_TIME
|
34
|
+
Worker.new(job[:file], @command_file).start
|
35
|
+
# Worker done remove it from the queue
|
36
|
+
@queue.pop(job[:file])
|
37
|
+
else
|
38
|
+
# File not ready yet
|
39
|
+
@queue.unreserve(job[:file]) unless job.nil?
|
40
|
+
end
|
41
|
+
rescue => e
|
42
|
+
puts e.message
|
43
|
+
puts e.backtrace
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def process(file)
|
49
|
+
end
|
50
|
+
|
51
|
+
def escape_glob(glob)
|
52
|
+
if glob.class == String
|
53
|
+
Regexp.new(glob)
|
54
|
+
else
|
55
|
+
glob
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
module Conveyor
|
2
|
+
# Handle the incoming watch requests and assign the workers
|
3
|
+
class Foreman
|
4
|
+
include Singleton
|
5
|
+
include Conveyor::Output
|
6
|
+
|
7
|
+
attr_accessor :workers, :channel, :config
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
loglvl(:debug)
|
11
|
+
read_configs
|
12
|
+
|
13
|
+
@listeners = {}
|
14
|
+
@belts = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def logfile
|
18
|
+
@config[:logfile]
|
19
|
+
end
|
20
|
+
|
21
|
+
def name
|
22
|
+
'Foreman'
|
23
|
+
end
|
24
|
+
|
25
|
+
def channel
|
26
|
+
@channel ||= EM::Channel.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def read_configs
|
30
|
+
@config = {
|
31
|
+
"worker_defs" => File.expand_path('.workers', Dir.pwd),
|
32
|
+
"logfile" => File.expand_path('log/conveyor.log', Dir.pwd),
|
33
|
+
"threadpool" => 5,
|
34
|
+
"websocket" => {
|
35
|
+
"disabled" => false,
|
36
|
+
"host" => "0.0.0.0",
|
37
|
+
"port" => 9876
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
@config_file = '.conveyor'
|
42
|
+
if File.exists? @config_file
|
43
|
+
@config.merge! YAML.load(File.open(@config_file))
|
44
|
+
elsif File.exists?('~/.conveyor')
|
45
|
+
@config_file = '~/.conveyor'
|
46
|
+
@config.merge! YAML.load(File.open(@config_file))
|
47
|
+
else
|
48
|
+
write_config(@config)
|
49
|
+
end
|
50
|
+
|
51
|
+
# New version of conveyor update config file with new params
|
52
|
+
if !@config['version'] || @config['version'] != Conveyor::VERSION
|
53
|
+
@config['version'] = Conveyor::VERSION
|
54
|
+
write_config(@config)
|
55
|
+
end
|
56
|
+
|
57
|
+
@config.symbolize_keys!
|
58
|
+
@config[:websocket].symbolize_keys!
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_config(config)
|
62
|
+
File.open(@config_file, 'w') { |fp| fp << config.to_yaml }
|
63
|
+
end
|
64
|
+
|
65
|
+
def watch(*args, &block)
|
66
|
+
@listener_opts = args.extract_options!
|
67
|
+
@listener_dir = File.expand_path(args.first)
|
68
|
+
raise "Directory #{@listener_dir} not found" unless File.directory? @listener_dir
|
69
|
+
|
70
|
+
@listener_opts[:latency] ||= 1
|
71
|
+
# Set a large latency if we force polling, prevents high cpu usage
|
72
|
+
@listener_opts[:latency] = 1 if @listener_opts[:latency] < 1 and @listener_opts[:force_polling]
|
73
|
+
|
74
|
+
yield
|
75
|
+
end
|
76
|
+
|
77
|
+
def match(*args, &block)
|
78
|
+
opts = args.extract_options!
|
79
|
+
debug "Filters: #{args.inspect}"
|
80
|
+
|
81
|
+
listener = Listen.to(@listener_dir)
|
82
|
+
if @listener_opts[:latency]
|
83
|
+
listener.latency(@listener_opts[:latency])
|
84
|
+
else
|
85
|
+
listener.latency(0.5)
|
86
|
+
end
|
87
|
+
|
88
|
+
listener.ignore(opts[:ignore]) if @listener_opts[:ignore]
|
89
|
+
if @listener_opts[:force_polling]
|
90
|
+
debug "Force polling"
|
91
|
+
listener.force_polling(true)
|
92
|
+
end
|
93
|
+
listener.filter(*args)
|
94
|
+
|
95
|
+
b = @belts[@listener_dir] = Belt.new(@listener_dir, @current_worker)
|
96
|
+
callback = lambda do |modified, added, removed|
|
97
|
+
begin
|
98
|
+
files = modified + added
|
99
|
+
b.touch(files) unless files.empty?
|
100
|
+
rescue => e
|
101
|
+
puts "Error: " + e.message
|
102
|
+
puts e.backtrace
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
listener.change(&callback)
|
107
|
+
@listeners[@listener_dir] = listener
|
108
|
+
rescue => e
|
109
|
+
error "ERROR: #{e.message}"
|
110
|
+
error e.backtrace
|
111
|
+
end
|
112
|
+
|
113
|
+
def file(glob)
|
114
|
+
/#{glob}$/
|
115
|
+
end
|
116
|
+
|
117
|
+
def extension(glob)
|
118
|
+
/\.#{glob}$/
|
119
|
+
end
|
120
|
+
|
121
|
+
def any
|
122
|
+
'*'
|
123
|
+
end
|
124
|
+
|
125
|
+
def notify_list
|
126
|
+
@notify_list.flatten!
|
127
|
+
@notify_list.uniq!
|
128
|
+
@notify_list
|
129
|
+
end
|
130
|
+
|
131
|
+
def stop!
|
132
|
+
@listeners.each { |dir,l| info "Stopping #{dir} listener"; l.stop }
|
133
|
+
@listeners = {}
|
134
|
+
@notify_list = []
|
135
|
+
end
|
136
|
+
|
137
|
+
def start
|
138
|
+
load!
|
139
|
+
@listeners.each do |k, listener|
|
140
|
+
info "Watching #{k}"
|
141
|
+
listener.start(false)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def output_status
|
146
|
+
status = @belts.collect { |dir, b| "#{b.name}: #{b.count}" }
|
147
|
+
print "\r#{status.join(', ')}"
|
148
|
+
end
|
149
|
+
|
150
|
+
def check
|
151
|
+
@belts.each do |dir, b|
|
152
|
+
EM.defer do
|
153
|
+
b.check
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def load!
|
159
|
+
stop!
|
160
|
+
|
161
|
+
info "Loading workers from #{@config[:worker_defs]}"
|
162
|
+
FileUtils.mkdir_p(@config[:worker_defs])
|
163
|
+
|
164
|
+
Dir.glob(File.join(@config[:worker_defs], '*.worker')) do |file|
|
165
|
+
begin
|
166
|
+
@current_worker = File.expand_path(file)
|
167
|
+
instance_eval File.read(@current_worker)
|
168
|
+
rescue => e
|
169
|
+
error [
|
170
|
+
"Error loading #{@current_worker}, skipping",
|
171
|
+
e.message,
|
172
|
+
e.backtrace
|
173
|
+
].flatten
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def method_missing(method, value = nil)
|
179
|
+
return method.to_s
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Conveyor
|
2
|
+
module Input
|
3
|
+
class Commands
|
4
|
+
class << self
|
5
|
+
def stop(*opts)
|
6
|
+
Kernel.exit
|
7
|
+
end
|
8
|
+
alias_method :exit, :stop
|
9
|
+
|
10
|
+
def listeners(*opts)
|
11
|
+
puts "Watching: "
|
12
|
+
puts "\t" + Conveyor::Foreman.instance.workers.keys.join("\n\t")
|
13
|
+
end
|
14
|
+
|
15
|
+
def unknown(cmd = nil)
|
16
|
+
puts "Unknown command #{cmd}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Conveyor
|
2
|
+
module Input
|
3
|
+
class Console
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
end
|
8
|
+
|
9
|
+
def listen
|
10
|
+
save_tty_settings
|
11
|
+
while line = Readline.readline('> ', true)
|
12
|
+
handle line
|
13
|
+
end
|
14
|
+
rescue Interrupt => e
|
15
|
+
restore_tty_settings
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle(line)
|
20
|
+
cmd = line.split(/\s+/)
|
21
|
+
return if cmd.empty?
|
22
|
+
|
23
|
+
if Commands.respond_to? cmd.first
|
24
|
+
Commands.send(cmd.shift, cmd.join(' '))
|
25
|
+
else
|
26
|
+
Commands.unknown(*cmd)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def save_tty_settings
|
31
|
+
@stty_save = `stty -g`.chomp
|
32
|
+
end
|
33
|
+
|
34
|
+
def restore_tty_settings
|
35
|
+
system('stty', @stty_save);
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Conveyor
|
2
|
+
module Output
|
3
|
+
class Channel
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
end
|
8
|
+
|
9
|
+
def write(name, msgtype, *msg)
|
10
|
+
@channel = Conveyor::Foreman.instance.channel
|
11
|
+
return false if @channel.nil?
|
12
|
+
|
13
|
+
options = msg.extract_options!
|
14
|
+
format = '[%s] [%s::%s] %s'
|
15
|
+
|
16
|
+
Array.new(msg).each do |m|
|
17
|
+
@channel.push [msgtype, sprintf(format, Time.now, name, msgtype, m)]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Conveyor
|
2
|
+
module Output
|
3
|
+
class Console
|
4
|
+
class << self
|
5
|
+
def output(*msg)
|
6
|
+
options = msg.extract_options!
|
7
|
+
options[:color] ||= :default
|
8
|
+
options[:tab] ||= 0
|
9
|
+
|
10
|
+
format = "\t"*options[:tab]
|
11
|
+
format << "\r[%s] %s"
|
12
|
+
if msg.class == Array
|
13
|
+
msg.each do |m|
|
14
|
+
puts sprintf(format, Time.now, m).color(options[:color])
|
15
|
+
end
|
16
|
+
else
|
17
|
+
puts sprintf(format, Time.now, msg).color(options[:color])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias_method :info, :output
|
21
|
+
alias_method :debug, :output
|
22
|
+
|
23
|
+
def warning(*msg)
|
24
|
+
options = msg.extract_options!
|
25
|
+
options[:color] ||= :yellow
|
26
|
+
msg.flatten!
|
27
|
+
output(*msg, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def error(*msg)
|
31
|
+
options = msg.extract_options!
|
32
|
+
options[:color] ||= :red
|
33
|
+
msg.flatten!
|
34
|
+
output(*msg, options)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Conveyor
|
2
|
+
module Output
|
3
|
+
class Email
|
4
|
+
class << self
|
5
|
+
def say(*msg)
|
6
|
+
# Do nothing
|
7
|
+
end
|
8
|
+
alias_method :info, :say
|
9
|
+
alias_method :debug, :say
|
10
|
+
|
11
|
+
def reset!
|
12
|
+
@msg_queue = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def warning(*msg)
|
16
|
+
# Do nothing
|
17
|
+
end
|
18
|
+
|
19
|
+
def error(*msg)
|
20
|
+
@msg_queue ||= []
|
21
|
+
options = msg.extract_options!
|
22
|
+
|
23
|
+
msg = msg.join("\n") if msg.class == Array
|
24
|
+
@msg_queue << msg
|
25
|
+
end
|
26
|
+
|
27
|
+
def mail
|
28
|
+
return if @msg_queue.nil? || @msg_queue.empty?
|
29
|
+
puts "Sending email to #{Conveyor::Foreman.instance.notify_list}"
|
30
|
+
puts @msg_queue
|
31
|
+
reset!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Conveyor
|
2
|
+
module Output
|
3
|
+
class Logfile
|
4
|
+
class << self
|
5
|
+
def write(logfile, name, msgtype, *msg)
|
6
|
+
return false if logfile.nil?
|
7
|
+
|
8
|
+
options = msg.extract_options!
|
9
|
+
|
10
|
+
format = '[%s] [%s::%s] %s'
|
11
|
+
|
12
|
+
if msg.class == Array
|
13
|
+
msg.each do |m|
|
14
|
+
output logfile,
|
15
|
+
sprintf(format, Time.now, name, msgtype, m)
|
16
|
+
end
|
17
|
+
else
|
18
|
+
output logfile,
|
19
|
+
sprintf(format, Time.now, name, msgtype, msg)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def output(logfile, msg = nil, &block)
|
24
|
+
FileUtils.mkdir_p(File.dirname(logfile))
|
25
|
+
fp = File.open(logfile, 'a')
|
26
|
+
|
27
|
+
if block_given?
|
28
|
+
yield fp
|
29
|
+
elsif !msg.nil?
|
30
|
+
fp << msg + "\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
fp.close
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'conveyor/output/console'
|
2
|
+
require 'conveyor/output/email'
|
3
|
+
require 'conveyor/output/logfile'
|
4
|
+
require 'conveyor/output/channel'
|
5
|
+
|
6
|
+
module Conveyor
|
7
|
+
module Output
|
8
|
+
MSGLVLS = {
|
9
|
+
:debug => 1,
|
10
|
+
:info => 10,
|
11
|
+
:warning => 20,
|
12
|
+
:error => 30
|
13
|
+
}
|
14
|
+
|
15
|
+
def should_log?(lvl, maxlvl = nil)
|
16
|
+
if maxlvl.nil? && @loglvl.nil?
|
17
|
+
loglvl :debug
|
18
|
+
should_log? lvl
|
19
|
+
elsif maxlvl.nil?
|
20
|
+
MSGLVLS[lvl.to_sym] >= @loglvl
|
21
|
+
else
|
22
|
+
MSGLVLS[lvl.to_sym] >= MSGLVLS[maxlvl.to_sym]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def loglvl(lvl)
|
27
|
+
@loglvl = MSGLVLS[lvl.to_sym] || MSGLVLS[:debug]
|
28
|
+
end
|
29
|
+
|
30
|
+
# Overrite this method to control logfile used
|
31
|
+
def logfile
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
|
35
|
+
# Override this method to control name used
|
36
|
+
def name
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def say(*msg)
|
41
|
+
output(:info, *msg)
|
42
|
+
end
|
43
|
+
|
44
|
+
def info(*msg)
|
45
|
+
output(:info, *msg)
|
46
|
+
end
|
47
|
+
|
48
|
+
def warning(*msg)
|
49
|
+
output(:warning, *msg)
|
50
|
+
end
|
51
|
+
|
52
|
+
def error(*msg)
|
53
|
+
output(:error, *msg)
|
54
|
+
end
|
55
|
+
|
56
|
+
def debug(*msg)
|
57
|
+
output(:debug, *msg)
|
58
|
+
end
|
59
|
+
|
60
|
+
def output(msgtype, *msg)
|
61
|
+
return false unless should_log?(msgtype)
|
62
|
+
Console.send(msgtype, *msg)
|
63
|
+
Logfile.write(logfile, name, msgtype, *msg)
|
64
|
+
Email.send(msgtype, *msg)
|
65
|
+
Channel.instance.write(name, msgtype, *msg)
|
66
|
+
end
|
67
|
+
|
68
|
+
def send_notifications
|
69
|
+
Email.mail
|
70
|
+
end
|
71
|
+
|
72
|
+
def notify(*emails)
|
73
|
+
Conveyor::Foreman.instance.notify_list << emails
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|