rest-ftp-daemon 0.250.0 → 0.250.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +2 -1
- data/config.ru +2 -2
- data/lib/rest-ftp-daemon.rb +1 -1
- data/lib/rest-ftp-daemon/api/dashboard.rb +0 -3
- data/lib/rest-ftp-daemon/api/job_presenter.rb +1 -1
- data/lib/rest-ftp-daemon/api/jobs.rb +1 -1
- data/lib/rest-ftp-daemon/api/status.rb +17 -9
- data/lib/rest-ftp-daemon/constants.rb +10 -2
- data/lib/rest-ftp-daemon/{stats.rb → counters.rb} +2 -2
- data/lib/rest-ftp-daemon/helpers.rb +3 -3
- data/lib/rest-ftp-daemon/job.rb +48 -48
- data/lib/rest-ftp-daemon/job_queue.rb +34 -47
- data/lib/rest-ftp-daemon/logger.rb +0 -3
- data/lib/rest-ftp-daemon/paginate.rb +0 -2
- data/lib/rest-ftp-daemon/remote.rb +0 -4
- data/lib/rest-ftp-daemon/remote_ftp.rb +0 -5
- data/lib/rest-ftp-daemon/remote_sftp.rb +0 -5
- data/lib/rest-ftp-daemon/settings.rb +0 -1
- data/lib/rest-ftp-daemon/views/dashboard.haml +1 -7
- data/lib/rest-ftp-daemon/views/{dashboard_stats.haml → dashboard_counters.haml} +2 -3
- data/lib/rest-ftp-daemon/views/dashboard_footer.haml +0 -3
- data/lib/rest-ftp-daemon/views/dashboard_header.haml +2 -4
- data/lib/rest-ftp-daemon/views/dashboard_jobs.haml +3 -6
- data/lib/rest-ftp-daemon/views/dashboard_rates.haml +7 -11
- data/lib/rest-ftp-daemon/views/dashboard_table.haml +12 -14
- data/lib/rest-ftp-daemon/views/dashboard_workers.haml +3 -2
- data/lib/rest-ftp-daemon/worker.rb +0 -1
- data/lib/rest-ftp-daemon/worker_job.rb +1 -3
- data/rest-ftp-daemon.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9162a08e5a91acc98b1fd1f8fe6f56fe06546f35
|
4
|
+
data.tar.gz: ae4b76ce6b9dbf8ff240797c5365d453430ca1d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc0ec566787db7bbb2dfb9c54941e80dc070a868ab7fa1b643f311acb0c893675b4067ee5645bd557a29327d0fbd9992b20bce88f2ff7b0ecd1e719258e314b4
|
7
|
+
data.tar.gz: 48d4bf8f2576b314a03cf33a3dace71000aaa23efc6c54e99af19541f14b89d593ee9a9508e533e2ed470f4deb3ad822b2c70ce054702fc5a9e562550b9b9133
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rest-ftp-daemon (0.250.
|
4
|
+
rest-ftp-daemon (0.250.3)
|
5
5
|
double-bag-ftps
|
6
6
|
facter
|
7
7
|
get_process_mem
|
@@ -13,7 +13,7 @@ PATH
|
|
13
13
|
newrelic_rpm
|
14
14
|
settingslogic
|
15
15
|
sys-cpu
|
16
|
-
thin (~> 1.6
|
16
|
+
thin (~> 1.6)
|
17
17
|
|
18
18
|
GEM
|
19
19
|
remote: http://rubygems.org/
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ rest-ftp-daemon
|
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/rest-ftp-daemon.svg)](http://badge.fury.io/rb/rest-ftp-daemon)
|
5
5
|
[![Code Climate](https://codeclimate.com/github/bmedici/rest-ftp-daemon/badges/gpa.svg)](https://codeclimate.com/github/bmedici/rest-ftp-daemon)
|
6
6
|
[![Test Coverage](https://codeclimate.com/github/bmedici/rest-ftp-daemon/badges/coverage.svg)](https://codeclimate.com/github/bmedici/rest-ftp-daemon/coverage)
|
7
|
-
|
7
|
+
[ ![Codeship](https://codeship.com/projects/46492fd0-00a4-0134-6639-66759d382560/status?branch=master)](https://codeship.com/projects/153245)
|
8
8
|
|
9
9
|
A pretty simple but configurable and efficient FTP-client daemon, driven
|
10
10
|
through a RESTful API. Create transfer jobs by POSTing a simple JSON structure,
|
@@ -28,6 +28,7 @@ Features
|
|
28
28
|
* static path pointers in configuration to abstract local mounts or remote FTPs (endpoint tokens)
|
29
29
|
* local source path and local/remote target path can use patterns to match multiple files (`/dir/file*.jpg`)
|
30
30
|
* several file transfer protocols supported: FTPs, FTPes, sFTP
|
31
|
+
* display bitrate to any pool or any FTP destination currently transferring (API and dashboard)
|
31
32
|
|
32
33
|
* Job management
|
33
34
|
* highly parrallel job processing using dedicated worker threads with their own context
|
data/config.ru
CHANGED
@@ -6,8 +6,8 @@ require "rest-ftp-daemon"
|
|
6
6
|
# Create global queue
|
7
7
|
$queue = RestFtpDaemon::JobQueue.new
|
8
8
|
|
9
|
-
# Create global
|
10
|
-
$
|
9
|
+
# Create global counters
|
10
|
+
$counters = RestFtpDaemon::Counters.new
|
11
11
|
|
12
12
|
# Initialize workers and conchita subsystem
|
13
13
|
$pool = RestFtpDaemon::WorkerPool.new
|
data/lib/rest-ftp-daemon.rb
CHANGED
@@ -25,7 +25,7 @@ require_relative "rest-ftp-daemon/logger"
|
|
25
25
|
require_relative "rest-ftp-daemon/paginate"
|
26
26
|
require_relative "rest-ftp-daemon/uri"
|
27
27
|
require_relative "rest-ftp-daemon/job_queue"
|
28
|
-
require_relative "rest-ftp-daemon/
|
28
|
+
require_relative "rest-ftp-daemon/counters"
|
29
29
|
require_relative "rest-ftp-daemon/worker"
|
30
30
|
require_relative "rest-ftp-daemon/worker_conchita"
|
31
31
|
require_relative "rest-ftp-daemon/worker_job"
|
@@ -8,6 +8,20 @@ module RestFtpDaemon
|
|
8
8
|
get "/" do
|
9
9
|
mem = GetProcessMem.new
|
10
10
|
status 200
|
11
|
+
|
12
|
+
# Get counters
|
13
|
+
counters = $counters.stats
|
14
|
+
|
15
|
+
# Amend counters with legacy attributes
|
16
|
+
if counters[:jobs].is_a? Hash
|
17
|
+
counters[:jobs_finished] = counters[:jobs][:finished] || 0
|
18
|
+
counters[:jobs_failed] = counters[:jobs][:failed] || 0
|
19
|
+
end
|
20
|
+
if counters[:data].is_a? Hash
|
21
|
+
counters[:transferred] = counters[:data][:transferred] || 0
|
22
|
+
end
|
23
|
+
|
24
|
+
# Generate sutrcture
|
11
25
|
return {
|
12
26
|
hostname: `hostname`.to_s.chomp,
|
13
27
|
version: APP_VER,
|
@@ -18,21 +32,15 @@ module RestFtpDaemon
|
|
18
32
|
memory_bytes: mem.bytes.to_i,
|
19
33
|
memory_mb: mem.mb.round(0),
|
20
34
|
|
21
|
-
|
22
|
-
|
35
|
+
status: $queue.jobs_by_status,
|
23
36
|
jobs_count: $queue.jobs_count,
|
24
|
-
status: $queue.jobs_count_by_status,
|
25
37
|
|
26
|
-
|
27
|
-
|
38
|
+
counters: counters,
|
39
|
+
|
28
40
|
rate_by_pool: $queue.rate_by(:pool),
|
29
41
|
rate_by_targethost: $queue.rate_by(:targethost),
|
30
|
-
jobs_by_status: $queue.jobs_by_status,
|
31
|
-
|
32
|
-
#rates_per_host: $queue.rates_per_host,
|
33
42
|
|
34
43
|
workers: $pool.worker_variables,
|
35
|
-
#kpis: $queue.queued_ids,
|
36
44
|
}
|
37
45
|
end
|
38
46
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Terrific constants
|
2
2
|
APP_NAME = "rest-ftp-daemon"
|
3
3
|
APP_NICK = "rftpd"
|
4
|
-
APP_VER = "0.250.
|
4
|
+
APP_VER = "0.250.3"
|
5
5
|
|
6
6
|
# Provide default config file information
|
7
7
|
APP_LIB = File.expand_path(File.dirname(__FILE__))
|
@@ -57,6 +57,14 @@ JOB_STYLES = {
|
|
57
57
|
JOB_STATUS_RENAMING => :info,
|
58
58
|
}
|
59
59
|
|
60
|
+
|
61
|
+
# Jobs statuses
|
62
|
+
JOB_METHOD_FTP = "ftp"
|
63
|
+
JOB_METHOD_FTPS = "ftps"
|
64
|
+
JOB_METHOD_SFTP = "sftp"
|
65
|
+
JOB_METHOD_FILE = "file"
|
66
|
+
|
67
|
+
|
60
68
|
# Worker statuses
|
61
69
|
WORKER_STATUS_STARTING = "starting"
|
62
70
|
WORKER_STATUS_WAITING = "waiting"
|
@@ -66,7 +74,7 @@ WORKER_STATUS_TIMEOUT = "timeout"
|
|
66
74
|
WORKER_STATUS_CRASHED = "crashed"
|
67
75
|
WORKER_STATUS_CLEANING = "cleaning"
|
68
76
|
WORKER_STYLES = {
|
69
|
-
WORKER_STATUS_WAITING =>
|
77
|
+
WORKER_STATUS_WAITING => nil,
|
70
78
|
WORKER_STATUS_RUNNING => :info,
|
71
79
|
WORKER_STATUS_CRASHED => :danger,
|
72
80
|
WORKER_STATUS_FINISHED => :success,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module RestFtpDaemon
|
2
2
|
|
3
3
|
# Queue that stores all the Jobs waiting to be processed or fully processed
|
4
|
-
class
|
4
|
+
class Counters
|
5
5
|
attr_reader :stats
|
6
6
|
|
7
7
|
if Settings.newrelic_enabled?
|
@@ -22,7 +22,7 @@ module RestFtpDaemon
|
|
22
22
|
|
23
23
|
def get group, name
|
24
24
|
@mutex_stats.synchronize do
|
25
|
-
@stats[group][name] if @stats[group]
|
25
|
+
@stats[group][name] if @stats[group].is_a? Hash
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -78,11 +78,11 @@ module RestFtpDaemon
|
|
78
78
|
def self.job_method_label method
|
79
79
|
return if method.nil?
|
80
80
|
klass = case method
|
81
|
-
when
|
81
|
+
when JOB_METHOD_FILE
|
82
82
|
"label-primary"
|
83
|
-
when
|
83
|
+
when JOB_METHOD_FTP
|
84
84
|
"label-warning"
|
85
|
-
when
|
85
|
+
when JOB_METHOD_FTPS
|
86
86
|
"label-success"
|
87
87
|
else
|
88
88
|
"label-default"
|
data/lib/rest-ftp-daemon/job.rb
CHANGED
@@ -19,7 +19,6 @@ module RestFtpDaemon
|
|
19
19
|
attr_reader :error
|
20
20
|
attr_reader :status
|
21
21
|
attr_reader :runs
|
22
|
-
attr_reader :target_method
|
23
22
|
|
24
23
|
attr_reader :queued_at
|
25
24
|
attr_reader :updated_at
|
@@ -213,13 +212,6 @@ module RestFtpDaemon
|
|
213
212
|
end
|
214
213
|
end
|
215
214
|
|
216
|
-
def get attribute
|
217
|
-
@mutex.synchronize do
|
218
|
-
@infos || {}
|
219
|
-
@infos[attribute]
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
215
|
def weight
|
224
216
|
@weight = [
|
225
217
|
- @runs.to_i,
|
@@ -247,12 +239,12 @@ module RestFtpDaemon
|
|
247
239
|
end
|
248
240
|
|
249
241
|
def targethost
|
250
|
-
|
242
|
+
get_info :target, :host
|
251
243
|
end
|
252
244
|
|
253
|
-
def json_target
|
254
|
-
|
255
|
-
end
|
245
|
+
# def json_target
|
246
|
+
# utf8 get_info(:target, :method)
|
247
|
+
# end
|
256
248
|
|
257
249
|
def json_error
|
258
250
|
utf8 @error unless @error.nil?
|
@@ -262,6 +254,13 @@ module RestFtpDaemon
|
|
262
254
|
utf8 @status unless @status.nil?
|
263
255
|
end
|
264
256
|
|
257
|
+
def get_info level1, level2
|
258
|
+
@mutex.synchronize do
|
259
|
+
@infos || {}
|
260
|
+
@infos[level1][level2] if @infos[level1].is_a? Hash
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
265
264
|
protected
|
266
265
|
|
267
266
|
def expand_path path
|
@@ -304,21 +303,19 @@ module RestFtpDaemon
|
|
304
303
|
@runs += 1
|
305
304
|
|
306
305
|
# Init
|
307
|
-
@source_method = :file
|
308
|
-
@target_method = nil
|
309
306
|
@source_path = nil
|
310
307
|
|
311
308
|
# Prepare source
|
312
309
|
raise RestFtpDaemon::JobMissingAttribute unless @source
|
313
310
|
@source_path = expand_path @source
|
314
|
-
set_info :
|
315
|
-
set_info :
|
311
|
+
set_info :source, :path, @source_path
|
312
|
+
set_info :source, :method, JOB_METHOD_FILE
|
316
313
|
|
317
314
|
# Prepare target
|
318
315
|
raise RestFtpDaemon::JobMissingAttribute unless @target
|
319
316
|
target_uri = expand_url @target
|
320
|
-
set_info :
|
321
|
-
set_info :
|
317
|
+
set_info :target, :uri, target_uri.to_s
|
318
|
+
set_info :target, :host, target_uri.host
|
322
319
|
@target_path = Path.new target_uri.path, true
|
323
320
|
|
324
321
|
#puts "@target_path: #{@target_path.inspect}"
|
@@ -328,20 +325,23 @@ module RestFtpDaemon
|
|
328
325
|
|
329
326
|
if target_uri.is_a? URI::FTP
|
330
327
|
log_info "Job.prepare target_method FTP"
|
331
|
-
# set_info :
|
332
|
-
|
328
|
+
# set_info :target, :method, :ftp
|
329
|
+
set_info :target, :method, JOB_METHOD_FTP
|
330
|
+
#@target_method = :ftp
|
333
331
|
@remote = RemoteFTP.new target_uri, log_context
|
334
332
|
|
335
333
|
elsif (target_uri.is_a? URI::FTPES) || (target_uri.is_a? URI::FTPS)
|
336
334
|
log_info "Job.prepare target_method FTPES"
|
337
|
-
# set_info :
|
338
|
-
|
335
|
+
# set_info :target, :method, :ftpes
|
336
|
+
set_info :target, :method, JOB_METHOD_FTPS
|
337
|
+
# @target_method = :ftpes
|
339
338
|
@remote = RemoteFTP.new target_uri, log_context, ftpes: true
|
340
339
|
|
341
340
|
elsif target_uri.is_a? URI::SFTP
|
342
341
|
log_info "Job.prepare target_method SFTP"
|
343
|
-
# set_info :
|
344
|
-
|
342
|
+
# set_info :target, :method, :sftp
|
343
|
+
set_info :target, :method, JOB_METHOD_SFTP
|
344
|
+
# @target_method = :sftp
|
345
345
|
@remote = RemoteSFTP.new target_uri, log_context
|
346
346
|
|
347
347
|
else
|
@@ -360,13 +360,13 @@ module RestFtpDaemon
|
|
360
360
|
raise RestFtpDaemon::JobAssertionFailed, "run/1" unless @source_path
|
361
361
|
raise RestFtpDaemon::JobAssertionFailed, "run/2" unless @target_path
|
362
362
|
@transfer_sent = 0
|
363
|
-
set_info :
|
363
|
+
set_info :source, :processed, 0
|
364
364
|
|
365
365
|
# Guess source files from disk
|
366
366
|
set_status JOB_STATUS_CHECKING_SRC
|
367
367
|
sources = find_local @source_path
|
368
|
-
set_info :
|
369
|
-
set_info :
|
368
|
+
set_info :source, :count, sources.count
|
369
|
+
set_info :source, :files, sources.collect(&:full)
|
370
370
|
log_info "Job.run sources #{sources.collect(&:name)}"
|
371
371
|
raise RestFtpDaemon::JobSourceNotFound if sources.empty?
|
372
372
|
|
@@ -383,7 +383,7 @@ module RestFtpDaemon
|
|
383
383
|
|
384
384
|
# Compute total files size
|
385
385
|
@transfer_total = sources.collect(&:size).sum
|
386
|
-
set_info :
|
386
|
+
set_info :transfer, :total, @transfer_total
|
387
387
|
|
388
388
|
# Reset counters
|
389
389
|
@last_data = 0
|
@@ -404,7 +404,7 @@ module RestFtpDaemon
|
|
404
404
|
remote_push source, full_target
|
405
405
|
|
406
406
|
# Update counters
|
407
|
-
set_info :
|
407
|
+
set_info :source, :processed, source_processed += 1
|
408
408
|
end
|
409
409
|
|
410
410
|
# FTP transfer finished
|
@@ -434,18 +434,18 @@ module RestFtpDaemon
|
|
434
434
|
Thread.current.thread_variable_set :updated_at, now
|
435
435
|
end
|
436
436
|
|
437
|
-
def set_info
|
437
|
+
def set_info level1, level2, value
|
438
438
|
@mutex.synchronize do
|
439
439
|
@infos || {}
|
440
|
+
@infos[level1] ||= {}
|
440
441
|
|
441
442
|
# Force strings to UTF8
|
442
443
|
if value.is_a? Symbol
|
443
|
-
@infos[
|
444
|
+
@infos[level1][level2] = value.to_s.force_encoding(Encoding::UTF_8)
|
444
445
|
elsif value.is_a? String
|
445
|
-
|
446
|
-
@infos[attribute] = value.force_encoding(Encoding::UTF_8)
|
446
|
+
@infos[level1][level2] = value.dup.force_encoding(Encoding::UTF_8)
|
447
447
|
else
|
448
|
-
@infos[
|
448
|
+
@infos[level1][level2] = value
|
449
449
|
end
|
450
450
|
|
451
451
|
# Mark the job as updated
|
@@ -490,9 +490,9 @@ module RestFtpDaemon
|
|
490
490
|
set_status JOB_STATUS_DISCONNECTING
|
491
491
|
@finished_at = Time.now
|
492
492
|
|
493
|
-
# Update
|
494
|
-
$
|
495
|
-
$
|
493
|
+
# Update counters
|
494
|
+
$counters.increment :jobs, :finished
|
495
|
+
$counters.add :data, :transferred, @transfer_total
|
496
496
|
end
|
497
497
|
|
498
498
|
def remote_push source, target
|
@@ -503,7 +503,7 @@ module RestFtpDaemon
|
|
503
503
|
|
504
504
|
# Use source filename if target path provided none (typically with multiple sources)
|
505
505
|
log_info "Job.remote_push [#{source.name}]: [#{source.full}] > [#{target.full}]"
|
506
|
-
set_info :
|
506
|
+
set_info :source, :current, source.name
|
507
507
|
|
508
508
|
# Compute temp target name
|
509
509
|
tempname = nil
|
@@ -537,10 +537,10 @@ module RestFtpDaemon
|
|
537
537
|
|
538
538
|
# Compute final bitrate
|
539
539
|
global_transfer_bitrate = get_bitrate @transfer_total, (Time.now - transfer_started_at)
|
540
|
-
set_info :
|
540
|
+
set_info :transfer, :bitrate, global_transfer_bitrate.round(0)
|
541
541
|
|
542
542
|
# Done
|
543
|
-
set_info :
|
543
|
+
set_info :source, :current, nil
|
544
544
|
end
|
545
545
|
|
546
546
|
def progress transferred, name = ""
|
@@ -549,17 +549,17 @@ module RestFtpDaemon
|
|
549
549
|
|
550
550
|
# Update counters
|
551
551
|
@transfer_sent += transferred
|
552
|
-
set_info :
|
552
|
+
set_info :transfer, :sent, @transfer_sent
|
553
553
|
|
554
554
|
# Update job info
|
555
555
|
percent0 = (100.0 * @transfer_sent / @transfer_total).round(0)
|
556
|
-
set_info :progress, percent0
|
556
|
+
set_info :transfer, :progress, percent0
|
557
557
|
|
558
558
|
# Update job status after each NOTIFY_UPADE_STATUS
|
559
559
|
progressed_ago = (now.to_f - @progress_at.to_f)
|
560
560
|
if (!JOB_UPDATE_INTERVAL.to_f.zero?) && (progressed_ago > JOB_UPDATE_INTERVAL.to_f)
|
561
561
|
@current_bitrate = running_bitrate @transfer_sent
|
562
|
-
set_info :
|
562
|
+
set_info :transfer, :bitrate, @current_bitrate.round(0)
|
563
563
|
|
564
564
|
# Log progress
|
565
565
|
stack = []
|
@@ -644,21 +644,21 @@ module RestFtpDaemon
|
|
644
644
|
# Update job's internal status
|
645
645
|
set_status JOB_STATUS_FAILED
|
646
646
|
set_error error
|
647
|
-
set_info :
|
648
|
-
set_info :
|
647
|
+
set_info :error, :exception, exception.class.to_s
|
648
|
+
set_info :error, :message, exception.message
|
649
649
|
|
650
650
|
# Build status stack
|
651
651
|
notif_status = nil
|
652
652
|
if include_backtrace
|
653
|
-
set_info :
|
653
|
+
set_info :error, :backtrace, exception.backtrace
|
654
654
|
notif_status = {
|
655
655
|
backtrace: exception.backtrace,
|
656
656
|
}
|
657
657
|
end
|
658
658
|
|
659
659
|
# Increment counter for this error
|
660
|
-
$
|
661
|
-
$
|
660
|
+
$counters.increment :errors, error
|
661
|
+
$counters.increment :jobs, :failed
|
662
662
|
|
663
663
|
# Prepare notification if signal given
|
664
664
|
return unless event
|
@@ -16,16 +16,13 @@ module RestFtpDaemon
|
|
16
16
|
# Instance variables
|
17
17
|
@queues = {}
|
18
18
|
@waitings = {}
|
19
|
-
|
20
|
-
# @queue = []
|
21
|
-
# @waiting = []
|
22
|
-
|
23
19
|
@jobs = []
|
24
20
|
|
25
21
|
@queues.taint # enable tainted communication
|
26
22
|
@waitings.taint
|
27
|
-
|
28
23
|
taint
|
24
|
+
|
25
|
+
# Global mutex for the queue
|
29
26
|
@mutex = Mutex.new
|
30
27
|
|
31
28
|
# Logger
|
@@ -44,30 +41,42 @@ module RestFtpDaemon
|
|
44
41
|
prefixed_id @last_id
|
45
42
|
end
|
46
43
|
|
47
|
-
|
44
|
+
def jobs_queued
|
48
45
|
@queues
|
49
|
-
#@queues.map { |status, jobs| jobs.size }
|
50
46
|
end
|
51
47
|
|
52
|
-
# Statistics on average rates
|
53
48
|
def rate_by method_name
|
54
49
|
# Init
|
55
|
-
|
50
|
+
result = {}
|
56
51
|
return unless Job.new(0, {}).respond_to? method_name
|
57
52
|
|
58
|
-
#
|
59
|
-
|
60
|
-
|
61
|
-
|
53
|
+
# Select only running jobs
|
54
|
+
@jobs.each do |job|
|
55
|
+
|
56
|
+
# Compute jobs's group, next if empty
|
57
|
+
group = job.send(method_name)
|
58
|
+
next if group.nil?
|
62
59
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
60
|
+
# Initialize rate entry
|
61
|
+
result[group] ||= nil
|
62
|
+
|
63
|
+
# If job is not uploading, next !
|
64
|
+
next unless job.status == JOB_STATUS_UPLOADING
|
65
|
+
|
66
|
+
# Extract current rate, next if not available
|
67
|
+
rate = job.get_info :transfer, :bitrate
|
68
|
+
next if rate.nil?
|
69
|
+
|
70
|
+
|
71
|
+
# Add its current rate
|
72
|
+
result[group] ||= 0
|
73
|
+
#log_info " 2: #{result.inspect} (rate: #{rate})"
|
74
|
+
result[group] += rate
|
75
|
+
#log_info " 3: #{result.inspect}"
|
67
76
|
end
|
68
77
|
|
69
78
|
# Return the rate
|
70
|
-
|
79
|
+
result
|
71
80
|
end
|
72
81
|
|
73
82
|
# Queue infos
|
@@ -80,20 +89,18 @@ module RestFtpDaemon
|
|
80
89
|
@jobs.group_by { |job| job.status }.map { |status, jobs| statuses[status] = jobs.size }
|
81
90
|
statuses
|
82
91
|
end
|
83
|
-
alias jobs_count_by_status jobs_by_status
|
84
92
|
|
85
|
-
def jobs_ids
|
86
|
-
|
87
|
-
end
|
93
|
+
# def jobs_ids
|
94
|
+
# @jobs.collect(&:id)
|
95
|
+
# end
|
88
96
|
|
89
97
|
def empty?
|
90
98
|
@queue.empty?
|
91
99
|
end
|
92
100
|
|
93
|
-
def num_waiting
|
94
|
-
|
95
|
-
end
|
96
|
-
|
101
|
+
# def num_waiting
|
102
|
+
# @waiting.size
|
103
|
+
# end
|
97
104
|
|
98
105
|
# Queue access
|
99
106
|
def find_by_id id, prefixed = false
|
@@ -176,7 +183,7 @@ module RestFtpDaemon
|
|
176
183
|
|
177
184
|
# Status filtering: only those jobs
|
178
185
|
else
|
179
|
-
@jobs.select { |job| job.status
|
186
|
+
@jobs.select { |job| job.status == status.to_s }
|
180
187
|
|
181
188
|
end
|
182
189
|
end
|
@@ -222,26 +229,6 @@ module RestFtpDaemon
|
|
222
229
|
"#{@prefix}.#{id}"
|
223
230
|
end
|
224
231
|
|
225
|
-
def rates_by_status jobs
|
226
|
-
rates = {}
|
227
|
-
|
228
|
-
# Sub-group by status
|
229
|
-
jobs.group_by(&:status).each do |status, jobset|
|
230
|
-
|
231
|
-
# Extract bitrate values
|
232
|
-
bitrates = jobset.collect do |job|
|
233
|
-
job.get(:transfer_bitrate)
|
234
|
-
end
|
235
|
-
|
236
|
-
# Store their sum
|
237
|
-
rates[status] = bitrates.reject(&:nil?).sum
|
238
|
-
# rates["#{status}_ids"] = jobset.collect(&:id).join(', ')
|
239
|
-
end
|
240
|
-
|
241
|
-
# Return rates
|
242
|
-
rates
|
243
|
-
end
|
244
|
-
|
245
232
|
if Settings.newrelic_enabled?
|
246
233
|
add_transaction_tracer :push, category: :task
|
247
234
|
add_transaction_tracer :pop, category: :task
|
@@ -43,7 +43,6 @@ module RestFtpDaemon
|
|
43
43
|
log_info "RemoteFTP.present? [#{target.name}]"
|
44
44
|
|
45
45
|
rescue Net::FTPPermError
|
46
|
-
# log_info "RemoteFTP.present? [#{target.name}] NOT_FOUND"
|
47
46
|
return false
|
48
47
|
else
|
49
48
|
return size
|
@@ -102,9 +101,6 @@ module RestFtpDaemon
|
|
102
101
|
log_info "RemoteFTP.push to [#{destination.name}]"
|
103
102
|
|
104
103
|
@ftp.putbinaryfile source.full, target.name, @chunk_size do |data|
|
105
|
-
# Update the worker activity marker
|
106
|
-
# FIXME: worker_is_still_active
|
107
|
-
|
108
104
|
# Update job status after this block transfer
|
109
105
|
yield data.bytesize, destination.name
|
110
106
|
end
|
@@ -134,6 +130,5 @@ module RestFtpDaemon
|
|
134
130
|
@ftp.ftps_mode = DoubleBagFTPS::EXPLICIT
|
135
131
|
end
|
136
132
|
|
137
|
-
|
138
133
|
end
|
139
134
|
end
|
@@ -123,9 +123,6 @@ module RestFtpDaemon
|
|
123
123
|
# args[2] : data being written (as string)
|
124
124
|
# puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
|
125
125
|
|
126
|
-
# Update the worker activity marker
|
127
|
-
# FIXME: worker_is_still_active
|
128
|
-
|
129
126
|
# Update job status after this block transfer
|
130
127
|
yield args[2].length, destination.name
|
131
128
|
|
@@ -154,8 +151,6 @@ module RestFtpDaemon
|
|
154
151
|
def close
|
155
152
|
# Close init
|
156
153
|
super
|
157
|
-
|
158
|
-
# @sftp.close
|
159
154
|
end
|
160
155
|
|
161
156
|
def connected?
|
@@ -14,11 +14,7 @@
|
|
14
14
|
.container-fluid
|
15
15
|
= render :dashboard_header
|
16
16
|
|
17
|
-
|
18
17
|
.container-fluid
|
19
|
-
|
20
|
-
%br
|
21
|
-
|
22
18
|
.row
|
23
19
|
#box-jobs.col-md-12
|
24
20
|
= render :dashboard_jobs
|
@@ -29,13 +25,11 @@
|
|
29
25
|
|
30
26
|
#box-workers.col-md-3
|
31
27
|
= render :dashboard_workers
|
32
|
-
= render :dashboard_stats
|
33
28
|
|
34
29
|
#box-rates.col-md-3
|
30
|
+
= render :dashboard_counters
|
35
31
|
= render :dashboard_rates
|
36
32
|
|
37
|
-
|
38
33
|
.footer
|
39
34
|
.container-fluid
|
40
35
|
= render :dashboard_footer
|
41
|
-
|
@@ -1,5 +1,5 @@
|
|
1
1
|
-# coding: utf-8
|
2
|
-
%h2
|
2
|
+
%h2 Counters
|
3
3
|
|
4
4
|
%table.table.table-striped.table-hover.table-condensed
|
5
5
|
|
@@ -11,11 +11,10 @@
|
|
11
11
|
|
12
12
|
%tbody
|
13
13
|
|
14
|
-
- $
|
14
|
+
- $counters.stats.each do |group, values|
|
15
15
|
|
16
16
|
- values.each do |name, value|
|
17
17
|
%tr
|
18
18
|
%td= group
|
19
19
|
%td= name
|
20
20
|
%td.text-right= value
|
21
|
-
|
@@ -1,7 +1,6 @@
|
|
1
1
|
-# coding: utf-8
|
2
2
|
- info_procs = (Facter.value :processorcount).to_i
|
3
3
|
|
4
|
-
|
5
4
|
.footer-signature.pull-left
|
6
5
|
|
7
6
|
©
|
@@ -31,5 +30,3 @@
|
|
31
30
|
.btn-group.btn-group-sm
|
32
31
|
.btn.btn-default.btn-info Started
|
33
32
|
.btn.btn-default= Helpers.datetime_short(APP_STARTED)
|
34
|
-
|
35
|
-
|
@@ -2,8 +2,8 @@
|
|
2
2
|
- info_procs = (Facter.value :processorcount).to_i
|
3
3
|
- info_load = Sys::CPU.load_avg.first.to_f
|
4
4
|
- info_norm = info_procs.zero? ? "N/A" : (100 * info_load / info_procs).round(1)
|
5
|
-
- info_trans = $
|
6
|
-
- info_processed = $
|
5
|
+
- info_trans = $counters.get :data, :transferred
|
6
|
+
- info_processed = $counters.get :jobs, :processed
|
7
7
|
- mem = GetProcessMem.new
|
8
8
|
|
9
9
|
|
@@ -36,5 +36,3 @@
|
|
36
36
|
.btn-group.btn-group-sm
|
37
37
|
.btn.btn-default.btn-success Transferred
|
38
38
|
.btn.btn-default= Helpers.format_bytes(info_trans, "B", 1)
|
39
|
-
|
40
|
-
|
@@ -1,5 +1,5 @@
|
|
1
1
|
-# coding: utf-8
|
2
|
-
-
|
2
|
+
- jobs_by_status = $queue.jobs_by_status
|
3
3
|
- counts_all = $queue.jobs_count
|
4
4
|
- jobs = @paginate.subset
|
5
5
|
|
@@ -9,7 +9,7 @@
|
|
9
9
|
ALL (#{counts_all})
|
10
10
|
|
11
11
|
.btn-group.btn-group-xs.filters
|
12
|
-
-
|
12
|
+
- jobs_by_status.each do |status, count|
|
13
13
|
- klass = (status.to_s == @filter) ? "btn-info" : ""
|
14
14
|
%a.btn.btn-default{href: Helpers.dashboard_filter_url(status), class: klass}
|
15
15
|
#{status} (#{count})
|
@@ -33,7 +33,7 @@
|
|
33
33
|
%th label
|
34
34
|
%th pool
|
35
35
|
%th source
|
36
|
-
%th
|
36
|
+
%th method
|
37
37
|
%th target
|
38
38
|
%th queued
|
39
39
|
%th.error status
|
@@ -44,7 +44,6 @@
|
|
44
44
|
%th{title: "Priority"} P
|
45
45
|
%th{title: "Runs count"} R
|
46
46
|
|
47
|
-
|
48
47
|
- @jobs_queued.each do |pool, jobs|
|
49
48
|
- unless jobs.empty?
|
50
49
|
%tbody.jobs
|
@@ -59,5 +58,3 @@
|
|
59
58
|
%tbody.jobs
|
60
59
|
= render :dashboard_table, {jobs: jobs}
|
61
60
|
|
62
|
-
|
63
|
-
|
@@ -13,24 +13,20 @@
|
|
13
13
|
%thead
|
14
14
|
%tr
|
15
15
|
%th= group_title
|
16
|
-
%th.text-right
|
17
|
-
%th.text-right=JOB_STATUS_UPLOADING
|
16
|
+
%th.text-right bitrate
|
18
17
|
|
19
18
|
%tbody
|
20
|
-
- rates_by_status.each do |group,
|
19
|
+
- rates_by_status.each do |group, rate|
|
21
20
|
- next if group.nil?
|
21
|
+
- trclass = (rate.nil? ? "" : "info")
|
22
22
|
|
23
|
-
%tr
|
24
|
-
%td
|
23
|
+
%tr{class: trclass}
|
24
|
+
%td
|
25
|
+
= group
|
25
26
|
%td.text-right
|
26
|
-
= Helpers.format_bytes(
|
27
|
-
%td.text-right
|
28
|
-
= Helpers.format_bytes(rates[JOB_STATUS_UPLOADING], "bps")
|
29
|
-
-# %td= rates.inspect
|
27
|
+
= Helpers.format_bytes(rate, "bps")
|
30
28
|
|
31
29
|
%thead
|
32
30
|
%tr
|
33
31
|
%td{colspan: 3}
|
34
32
|
%br
|
35
|
-
|
36
|
-
-# JOB_STATUS_UPLOADING
|
@@ -1,10 +1,10 @@
|
|
1
1
|
-# coding: utf-8
|
2
2
|
- jobs.each do |job|
|
3
|
-
- progress = job.
|
4
|
-
- source_count = job.
|
5
|
-
- source_processed = job.
|
6
|
-
- source_current = job.
|
7
|
-
- bitrate = job.
|
3
|
+
- progress = job.get_info(:transfer, :progress)
|
4
|
+
- source_count = job.get_info(:source, :count) || 0
|
5
|
+
- source_processed = job.get_info(:source, :processed) || 0
|
6
|
+
- source_current = job.get_info(:source, :current)
|
7
|
+
- bitrate = job.get_info(:transfer, :bitrate)
|
8
8
|
- trclass = JOB_STYLES[job.status]
|
9
9
|
- runs = job.runs.to_i
|
10
10
|
|
@@ -20,14 +20,14 @@
|
|
20
20
|
|
21
21
|
%td= job.pool
|
22
22
|
|
23
|
-
%td{title: job.
|
23
|
+
%td{title: job.get_info(:source, :path)}
|
24
24
|
= Helpers.highlight_tokens job.source
|
25
25
|
|
26
26
|
%td
|
27
|
-
|
28
|
-
|
27
|
+
= Helpers.job_method_label (job.get_info :target, :method)
|
28
|
+
=# Helpers.job_method_label job.target_method
|
29
29
|
|
30
|
-
%td{title: job.
|
30
|
+
%td{title: job.get_info(:target, :url)}
|
31
31
|
= Helpers.highlight_tokens job.target
|
32
32
|
|
33
33
|
%td
|
@@ -54,14 +54,14 @@
|
|
54
54
|
- if job.status == JOB_STATUS_UPLOADING
|
55
55
|
.progress
|
56
56
|
.progress-bar{style:"width: #{progress}%;"}
|
57
|
-
= Helpers.format_bytes(job.
|
57
|
+
= Helpers.format_bytes(job.get_info(:transfer, :sent), "B")
|
58
58
|
|
59
59
|
- else
|
60
|
-
.error{title: job.
|
60
|
+
.error{title: job.get_info(:error, :message)}
|
61
61
|
= Helpers.text_or_empty(job.error)
|
62
62
|
|
63
63
|
%td.nobr.text-right
|
64
|
-
= Helpers.format_bytes(job.
|
64
|
+
= Helpers.format_bytes(job.get_info(:transfer, :total), "B")
|
65
65
|
|
66
66
|
%td.nobr.text-right{title: "time: #{job.exectime} s"}
|
67
67
|
- if bitrate
|
@@ -78,5 +78,3 @@
|
|
78
78
|
|
79
79
|
%td
|
80
80
|
.label.flag.worker-label{class: Helpers.job_runs_style(runs)}= runs
|
81
|
-
|
82
|
-
|
@@ -1,4 +1,6 @@
|
|
1
1
|
-# coding: utf-8
|
2
|
+
- variables = $pool.worker_variables
|
3
|
+
|
2
4
|
%h2 Workers
|
3
5
|
|
4
6
|
%table.table.table-striped.table-hover.table-condensed
|
@@ -12,7 +14,7 @@
|
|
12
14
|
%th.text-right seen
|
13
15
|
|
14
16
|
%tbody
|
15
|
-
-
|
17
|
+
- variables.each do |vars|
|
16
18
|
- wid = vars[:wid]
|
17
19
|
- status = vars[:status]
|
18
20
|
- alive = $pool.worker_alive? wid
|
@@ -22,7 +24,6 @@
|
|
22
24
|
- trclass = "danger"
|
23
25
|
- status = "DEAD"
|
24
26
|
|
25
|
-
|
26
27
|
%tr{class: trclass.to_s}
|
27
28
|
%td= vars[:pool]
|
28
29
|
%td= wid
|
@@ -35,8 +35,6 @@ module RestFtpDaemon
|
|
35
35
|
max_age = Settings.at(:retry, :max_age)
|
36
36
|
max_runs = Settings.at(:retry, :max_runs)
|
37
37
|
delay = Settings.at(:retry, :delay)
|
38
|
-
# log_error "on_errors: #{on_errors.inspect} (#{on_errors.first.class})"
|
39
|
-
# log_error "job.error: #{job.error} (#{job.error.class})"
|
40
38
|
|
41
39
|
if !job.error
|
42
40
|
#log_info "job succeeded"
|
@@ -86,7 +84,7 @@ module RestFtpDaemon
|
|
86
84
|
worker_status WORKER_STATUS_FINISHED, job
|
87
85
|
|
88
86
|
# Increment total processed jobs count
|
89
|
-
$
|
87
|
+
$counters.increment :jobs, :processed
|
90
88
|
|
91
89
|
rescue RestFtpDaemon::JobTimeout => ex
|
92
90
|
log_error "JOB TIMED OUT", ex.backtrace
|
data/rest-ftp-daemon.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency "rubocop", "~> 0.32.0"
|
32
32
|
spec.add_development_dependency "pry"
|
33
33
|
|
34
|
-
spec.add_runtime_dependency "thin", "~> 1.6
|
34
|
+
spec.add_runtime_dependency "thin", "~> 1.6"
|
35
35
|
spec.add_runtime_dependency "grape"
|
36
36
|
spec.add_runtime_dependency "grape-entity"
|
37
37
|
spec.add_runtime_dependency "settingslogic"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-ftp-daemon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.250.
|
4
|
+
version: 0.250.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bruno MEDICI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 1.6
|
103
|
+
version: '1.6'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 1.6
|
110
|
+
version: '1.6'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: grape
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -291,6 +291,7 @@ files:
|
|
291
291
|
- lib/rest-ftp-daemon/api/status.rb
|
292
292
|
- lib/rest-ftp-daemon/array.rb
|
293
293
|
- lib/rest-ftp-daemon/constants.rb
|
294
|
+
- lib/rest-ftp-daemon/counters.rb
|
294
295
|
- lib/rest-ftp-daemon/exceptions.rb
|
295
296
|
- lib/rest-ftp-daemon/helpers.rb
|
296
297
|
- lib/rest-ftp-daemon/job.rb
|
@@ -308,14 +309,13 @@ files:
|
|
308
309
|
- lib/rest-ftp-daemon/settings.rb
|
309
310
|
- lib/rest-ftp-daemon/static/css/bootstrap.css
|
310
311
|
- lib/rest-ftp-daemon/static/css/main.css
|
311
|
-
- lib/rest-ftp-daemon/stats.rb
|
312
312
|
- lib/rest-ftp-daemon/uri.rb
|
313
313
|
- lib/rest-ftp-daemon/views/dashboard.haml
|
314
|
+
- lib/rest-ftp-daemon/views/dashboard_counters.haml
|
314
315
|
- lib/rest-ftp-daemon/views/dashboard_footer.haml
|
315
316
|
- lib/rest-ftp-daemon/views/dashboard_header.haml
|
316
317
|
- lib/rest-ftp-daemon/views/dashboard_jobs.haml
|
317
318
|
- lib/rest-ftp-daemon/views/dashboard_rates.haml
|
318
|
-
- lib/rest-ftp-daemon/views/dashboard_stats.haml
|
319
319
|
- lib/rest-ftp-daemon/views/dashboard_table.haml
|
320
320
|
- lib/rest-ftp-daemon/views/dashboard_tokens.haml
|
321
321
|
- lib/rest-ftp-daemon/views/dashboard_workers.haml
|