rest-ftp-daemon 0.250.0 → 0.250.3
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.
- 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
|
[](http://badge.fury.io/rb/rest-ftp-daemon)
|
5
5
|
[](https://codeclimate.com/github/bmedici/rest-ftp-daemon)
|
6
6
|
[](https://codeclimate.com/github/bmedici/rest-ftp-daemon/coverage)
|
7
|
-
|
7
|
+
[ ](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
|