rest-ftp-daemon 0.202.2 → 0.210.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a84dfb4963cc92d2a504f0fbad4670ea68f37fce
4
- data.tar.gz: f6dfe45e4adb40227e70396df77b2b3691a78fd6
3
+ metadata.gz: ad1215dadf62110ff9e20ee3e5100c7af016c258
4
+ data.tar.gz: e5e14d4cd2f4bf5170915e4a8ab0f2fde3046c59
5
5
  SHA512:
6
- metadata.gz: b8d407b7aaef242722cd7e60bea9829650fcb55f21660471ac2335dd24383d5100f30f15e75e6cfe995718f166e3efc3c01e5f7b2f40e3147fdc8e529dc48602
7
- data.tar.gz: a5f1c2d24a5498017c5c6c6eaa34779950006648e0d8e57b59bd8f59836bd41168538c34a3e39103ed887fc4fe36b6e591bc679c605740956124a8ac504bbac5
6
+ metadata.gz: 0f67f2a19ef8e17abc200bce126192127595c8c8e3c712840e23fffbf462bd0b06221f1e3c828c4fe46c334f834bc8312de60b42d9cdedd02f25ac63d0028dd2
7
+ data.tar.gz: af5f5a20d55f85cbe5213f2db1f6ed5593c538283c2add01608a34eff6a20e322620f0123b365457859f9d731bf6a6a0efdb6c2a08556ac4bf39fe64ce921a89
data/.gitignore CHANGED
@@ -3,5 +3,5 @@ pkg
3
3
  .DS_Store
4
4
  *.log
5
5
  tmp/
6
- work/
7
- rest-ftp-daemon.yml
6
+ DOC/
7
+ rest-ftp-daemon.yml
@@ -5,17 +5,24 @@ require 'grape'
5
5
  require 'grape-entity'
6
6
  require 'haml'
7
7
  require 'facter'
8
+ require 'uri'
9
+ require 'securerandom'
10
+ require 'timeout'
8
11
  require 'sys/cpu'
9
12
  require 'syslog'
13
+ require 'net/ftp'
14
+ require 'net/http'
15
+ require 'double_bag_ftps'
10
16
 
11
17
 
12
- # My libs
18
+ # Project's libs
13
19
  require 'rest-ftp-daemon/constants'
14
20
  require 'rest-ftp-daemon/settings'
15
21
  require 'rest-ftp-daemon/exceptions'
16
22
  require 'rest-ftp-daemon/helpers'
17
23
  require 'rest-ftp-daemon/uri'
18
24
  require 'rest-ftp-daemon/job_queue'
25
+ require 'rest-ftp-daemon/worker'
19
26
  require 'rest-ftp-daemon/worker_pool'
20
27
  require 'rest-ftp-daemon/logger'
21
28
  require 'rest-ftp-daemon/logger_pool'
@@ -3,6 +3,12 @@ module RestFtpDaemon
3
3
  class Root < Grape::API
4
4
 
5
5
 
6
+ ####### HELPERS
7
+
8
+ helpers do
9
+ end
10
+
11
+
6
12
  ####### DASHBOARD - GET /
7
13
 
8
14
  # Server global status
@@ -15,14 +21,18 @@ module RestFtpDaemon
15
21
  # Detect QS filters
16
22
  only = params["only"].to_s
17
23
 
18
- # Get jobs to display
19
- jobs = $queue.sorted_by_status(only)
24
+ # Get jobs for this view, order jobs by their weights
25
+ current = $queue.filter_jobs only
26
+
27
+ # Provide queue only if no filtering set
28
+ queue = []
29
+ queue = $queue.queue if only.empty?
20
30
 
21
31
  # Get workers status
22
- @worker_vars = $pool.worker_vars
32
+ @worker_variables = $pool.worker_variables
23
33
 
24
34
  # Compile haml template
25
- output = render :dashboard, {jobs: jobs, only: only}
35
+ output = render :dashboard, {queue: queue, current: current, only: only}
26
36
 
27
37
  # Send response
28
38
  env['api.format'] = :html
@@ -13,7 +13,8 @@ module RestFtpDaemon
13
13
 
14
14
  begin
15
15
  # Get job to display
16
- job = job_find params[:id]
16
+ raise RestFtpDaemon::JobNotFound if params[:id].nil?
17
+ job = $queue.find_by_id(params[:id]) || $queue.find_by_id(params[:id], true)
17
18
  raise RestFtpDaemon::JobNotFound if job.nil?
18
19
 
19
20
  rescue RestFtpDaemon::JobNotFound => exception
@@ -48,7 +49,8 @@ module RestFtpDaemon
48
49
  only = params["only"].to_s
49
50
 
50
51
  # Get jobs to display
51
- jobs = $queue.sorted_by_status(only)
52
+ # jobs = $queue.sorted_by_status(only)
53
+ jobs = $queue.jobs
52
54
 
53
55
  rescue RestFtpDaemonException => exception
54
56
  info "EXCEPTION: RestFtpDaemonException: #{exception.message}"
@@ -86,8 +88,8 @@ module RestFtpDaemon
86
88
  end
87
89
 
88
90
  post '/jobs/' do
89
- info "POST /jobs #{params.inspect}"
90
- # request.body.rewind
91
+ info "POST /jobs", params.collect {|name, value| "#{name}: #{value.inspect}"}
92
+
91
93
  begin
92
94
 
93
95
  # Create a new job
@@ -33,8 +33,10 @@ module RestFtpDaemon
33
33
 
34
34
  helpers do
35
35
 
36
- def info message, context = {}
37
- Root.logger.info_with_id message, context
36
+ def info message, lines = []
37
+ Root.logger.info_with_id message,
38
+ lines: lines,
39
+ origin: self.class.to_s
38
40
  end
39
41
 
40
42
  def api_error exception
@@ -50,13 +52,6 @@ module RestFtpDaemon
50
52
  haml_engine.render(binding, values)
51
53
  end
52
54
 
53
- def job_find job_id
54
- return nil if ($queue.all_size==0)
55
-
56
- # Find a job with exactly this id, or prefixed if not found
57
- $queue.find_by_id(job_id) || $queue.find_by_id(job_id, true)
58
- end
59
-
60
55
  end
61
56
 
62
57
  end
@@ -17,10 +17,9 @@ module RestFtpDaemon
17
17
  uptime: (Time.now - APP_STARTED).round(1),
18
18
  counters: $queue.counters,
19
19
  status: $queue.counts_by_status,
20
- vars: $pool.worker_vars,
21
- jobs_count: $queue.all_size,
22
- jobs_queued: $queue.queued.collect(&:id),
23
- jobs_popped: $queue.popped.collect(&:id),
20
+ workers: $pool.worker_variables,
21
+ jobs_count: $queue.jobs_count,
22
+ jobs_queued: $queue.queued_ids
24
23
  #routes: RestFtpDaemon::API::Root::routes,
25
24
  }
26
25
  end
@@ -1,31 +1,53 @@
1
1
  # Terrific constants
2
2
  APP_NAME = "rest-ftp-daemon"
3
- APP_VER = "0.202.2"
3
+ APP_VER = "0.210.0"
4
4
 
5
5
 
6
- # Logging
7
- DEFAULT_LOGS_PIPE_LEN = 10
8
- DEFAULT_LOGS_ID_LEN = 8
9
- DEFAULT_LOGS_TRIM_LINE = 80
6
+ # Jobs and workers
7
+ JOB_RANDOM_LEN = 8
8
+ JOB_IDENT_LEN = 4
9
+ JOB_TEMPFILE_LEN = 8
10
+ JOB_STATUS_UPLOADING = :uploading
11
+ JOB_STATUS_RENAMING = :renaming
12
+ JOB_STATUS_FINISHED = :finished
13
+ JOB_STATUS_FAILED = :failed
14
+ JOB_STATUS_QUEUED = :queued
10
15
 
11
16
 
12
- # Jobs identifiers length
13
- JOB_RANDOM_LEN = 8
14
- JOB_TEMPFILE_LEN = 8
15
- JOB_IDENT_LEN = 4
17
+ # Logging and startup
18
+ LOG_PIPE_LEN = 10
19
+ LOG_COL_WID = 4
20
+ LOG_COL_JID = JOB_IDENT_LEN+3+2
21
+ LOG_COL_ID = 6
22
+ LOG_TRIM_LINE = 80
16
23
 
17
24
 
18
- # Jobs
19
- JOB_UPDATE_KB = 2048
20
- JOB_STATUS_UPLOADING = :uploading
21
- JOB_STATUS_FINISHED = :finished
22
- JOB_STATUS_QUEUED = :queued
23
- JOB_WEIGHTS = {queued: -10, uploading: 10, finished: 50}
24
-
25
25
  # Notifications
26
- NOTIFY_PREFIX = "rftpd"
27
- NOTIFY_USERAGENT = "#{APP_NAME} - #{APP_VER}"
28
- NOTIFY_IDENTIFIER_LEN = 4
26
+ NOTIFY_PREFIX = "rftpd"
27
+ NOTIFY_USERAGENT = "#{APP_NAME} - #{APP_VER}"
28
+ NOTIFY_IDENTIFIER_LEN = 4
29
+
30
+
31
+ # Dashboard row styles
32
+ JOB_STYLES = {
33
+ JOB_STATUS_QUEUED => :active,
34
+ JOB_STATUS_FAILED => :warning,
35
+ JOB_STATUS_FINISHED => :success,
36
+ JOB_STATUS_UPLOADING => :info,
37
+ JOB_STATUS_RENAMING => :info,
38
+ }
39
+ WORKER_STYLES = {
40
+ :waiting => :success,
41
+ :processing => :info,
42
+ :crashed => :danger,
43
+ :done => :success,
44
+ :dead => :danger
45
+ }
46
+
47
+
48
+ # Configuration defaults
49
+ DEFAULT_WORKER_TIMEOUT = 3600
50
+ DEFAULT_FTP_CHUNK = 2048
29
51
 
30
52
 
31
53
  # Initialize defaults
@@ -8,6 +8,7 @@ module RestFtpDaemon
8
8
  class MissingPool < RestFtpDaemonException; end
9
9
 
10
10
  class JobException < RestFtpDaemonException; end
11
+ class JobTimeout < RestFtpDaemonException; end
11
12
  class JobNotFound < RestFtpDaemonException; end
12
13
  class JobUnresolvedTokens < RestFtpDaemonException; end
13
14
  class JobAssertionFailed < RestFtpDaemonException; end
@@ -1,5 +1,3 @@
1
- require 'securerandom'
2
-
3
1
  module RestFtpDaemon
4
2
  class Helpers
5
3
 
@@ -96,15 +94,15 @@ module RestFtpDaemon
96
94
  # Dates and times: date with time generator
97
95
  def self.datetime_full datetime
98
96
  return "-" if datetime.nil?
99
- return datetime.to_datetime.strftime("%d.%m.%Y %H:%M")
97
+ return datetime.to_datetime.strftime("%d.%m.%Y %H:%M:%S")
100
98
  end
101
99
 
102
100
  def self.datetime_short datetime
103
101
  # return param.class
104
102
  return "-" if datetime.nil?
105
103
  return "?" unless datetime.respond_to? :to_date
106
- return datetime.to_datetime.strftime("%H:%M") if datetime.to_date == Time.now.to_date
107
- return datetime.to_datetime.strftime("%d/%m %H:%M")
104
+ return datetime.to_datetime.strftime("%H:%M:%S") if datetime.to_date == Time.now.to_date
105
+ return datetime.to_datetime.strftime("%d/%m %H:%M:%S")
108
106
  end
109
107
 
110
108
  def self.hide_credentials_from_url url
@@ -1,8 +1,3 @@
1
- require 'uri'
2
- require 'net/ftp'
3
- require 'double_bag_ftps'
4
- require 'timeout'
5
-
6
1
  module RestFtpDaemon
7
2
  class Job
8
3
 
@@ -40,11 +35,8 @@ module RestFtpDaemon
40
35
  @status = nil
41
36
  @wid = nil
42
37
 
43
- # Debug mode
44
- @ftp_debug_enabled = (Settings.at :debug, :ftp) == true
45
-
46
38
  # Logger
47
- @logger = RestFtpDaemon::LoggerPool.instance.get :workers
39
+ @logger = RestFtpDaemon::LoggerPool.instance.get :jobs
48
40
 
49
41
  # Protect with a mutex
50
42
  @mutex = Mutex.new
@@ -59,22 +51,29 @@ module RestFtpDaemon
59
51
  flag_default :overwrite, false
60
52
  flag_default :tempfile, false
61
53
 
54
+ # Read source file size and parameters
55
+ @ftp_debug_enabled = (Settings.at :debug, :ftp) == true
56
+ update_every_kb = (Settings.transfer.update_every_kb rescue nil) || DEFAULT_FTP_CHUNK
57
+ @notify_after_sec = Settings.transfer.notify_after_sec rescue nil
58
+ @chunk_size = update_every_kb * 1024
59
+
62
60
  # Flag current job
63
61
  @queued_at = Time.now
62
+ @updated_at = Time.now
64
63
 
65
64
  # Send first notification
66
- info "Job.initialize notify: queued"
65
+ info "Job.initialize notify[queued] notify_after_sec[#{@notify_after_sec}] update_every_kb[#{@update_every_kb}]"
67
66
  client_notify :queued
68
67
  end
69
68
 
70
69
  def process
71
70
  # Update job's status
72
71
  @error = nil
72
+ info "Job.process starting"
73
73
 
74
74
  # Prepare job
75
75
  begin
76
- info "Job.process prepare"
77
- newstatus :preparing
76
+ newstatus :prepare
78
77
  prepare
79
78
 
80
79
  rescue RestFtpDaemon::JobMissingAttribute => exception
@@ -95,22 +94,25 @@ module RestFtpDaemon
95
94
  rescue RestFtpDaemon::JobAssertionFailed => exception
96
95
  return oops :started, exception, :assertion_failed
97
96
 
98
- rescue RestFtpDaemon::RestFtpDaemonException => exception
99
- return oops :started, exception, :prepare_failed, true
97
+ # rescue RestFtpDaemon::JobTimeout => exception
98
+ # info "Job.process propagate JobTimeout to Worker"
99
+ # raise RestFtpDaemon::JobTimeout
100
100
 
101
- rescue Exception => exception
102
- return oops :started, exception, :prepare_unhandled, true
101
+ # rescue RestFtpDaemon::RestFtpDaemonException => exception
102
+ # return oops :started, exception, :prepare_failed, true
103
+
104
+ # rescue Exception => exception
105
+ # return oops :started, exception, :prepare_unhandled, true
103
106
 
104
107
  else
105
108
  # Prepare done !
106
109
  newstatus :prepared
107
- info "Job.process notify: started"
110
+ info "Job.process notify[started]"
108
111
  client_notify :started
109
112
  end
110
113
 
111
114
  # Process job
112
115
  begin
113
- info "Job.process transfer"
114
116
  newstatus :starting
115
117
  transfer
116
118
 
@@ -162,16 +164,20 @@ module RestFtpDaemon
162
164
  rescue RestFtpDaemon::JobAssertionFailed => exception
163
165
  return oops :ended, exception, :assertion_failed
164
166
 
165
- rescue RestFtpDaemon::RestFtpDaemonException => exception
166
- return oops :ended, exception, :transfer_failed, true
167
+ # rescue RestFtpDaemon::JobTimeout => exception
168
+ # info "Job.process propagate JobTimeout to Worker"
169
+ # raise RestFtpDaemon::JobTimeout
170
+
171
+ # rescue RestFtpDaemon::RestFtpDaemonException => exception
172
+ # return oops :ended, exception, :transfer_failed, true
167
173
 
168
- rescue Exception => exception
169
- return oops :ended, exception, :transfer_unhandled, true
174
+ # rescue Exception => exception
175
+ # return oops :ended, exception, :transfer_unhandled, true
170
176
 
171
177
  else
172
178
  # All done !
173
179
  newstatus JOB_STATUS_FINISHED
174
- info "Job.process notify: ended"
180
+ info "Job.process notify[ended]"
175
181
  client_notify :ended
176
182
  end
177
183
 
@@ -184,16 +190,22 @@ module RestFtpDaemon
184
190
  end
185
191
  end
186
192
 
193
+ def weight
194
+ @weight = [@priority.to_i, -@queued_at.to_i]
195
+ end
196
+
187
197
  def set_queued
188
198
  # Update job status
189
199
  newstatus JOB_STATUS_QUEUED
190
200
  end
191
201
 
192
202
  def oops_after_crash exception
193
- # info "Yes, we crash!"
194
- return oops :crashed, exception, :crashed
203
+ return oops :ended, exception, :crashed
195
204
  end
196
205
 
206
+ def oops_you_stop_now exception
207
+ return oops :ended, exception, :timeout
208
+ end
197
209
 
198
210
  protected
199
211
 
@@ -338,8 +350,6 @@ module RestFtpDaemon
338
350
  # Handle each source file matched, and start a transfer
339
351
  done = 0
340
352
  source_matches.each do |filename|
341
- # Increment counter
342
-
343
353
  # Do the transfer, only if it's a file
344
354
  ftp_transfer filename, target_name
345
355
 
@@ -355,21 +365,20 @@ module RestFtpDaemon
355
365
 
356
366
  private
357
367
 
358
- def info message, context = {}
368
+ def info message, lines = []
359
369
  return if @logger.nil?
360
370
 
361
- # Inject context
362
- context[:id] = @id
363
- context[:origin] = self.class
364
-
365
371
  # Forward to logger
366
- @logger.info_with_id message, context
372
+ @logger.info_with_id message,
373
+ wid: @wid,
374
+ jid: @id,
375
+ lines: lines,
376
+ origin: self.class.to_s
367
377
  end
368
378
 
369
379
  def newstatus name
370
- # Update local status
371
380
  @status = name
372
- # push_job
381
+ worker_is_still_active
373
382
  end
374
383
 
375
384
  def flag_default name, default
@@ -518,7 +527,7 @@ module RestFtpDaemon
518
527
  end
519
528
 
520
529
  # Now we were able to chdir inside, just tell it
521
- info "#{pref} changed to [#{@ftp.pwd}]"
530
+ info "#{pref} > ftp.pwd [#{@ftp.pwd}]"
522
531
  end
523
532
 
524
533
  def ftp_presence target_name
@@ -565,10 +574,6 @@ module RestFtpDaemon
565
574
  end
566
575
  end
567
576
 
568
- # Read source file size and parameters
569
- update_every_kb = (Settings.transfer.update_every_kb rescue nil) || JOB_UPDATE_KB
570
- notify_after_sec = Settings.transfer.notify_after_sec rescue nil
571
-
572
577
  # Compute temp target name
573
578
  target_real = target_name
574
579
  if @tempfile
@@ -577,90 +582,103 @@ module RestFtpDaemon
577
582
  end
578
583
 
579
584
  # Start transfer
580
- chunk_size = update_every_kb * 1024
581
- t0 = tstart = Time.now
582
- notified_at = Time.now
585
+ transfer_started_at = Time.now
586
+ @transfer_pointer_at = transfer_started_at
587
+
588
+ @notified_at = Time.now
583
589
  newstatus JOB_STATUS_UPLOADING
584
590
 
585
- @ftp.putbinaryfile(source_filename, target_real, chunk_size) do |block|
586
- # Update counters
587
- @transfer_sent += block.bytesize
588
- set :transfer_sent, @transfer_sent
589
-
590
- # Update bitrate
591
- #dt = Time.now - t0
592
- bitrate0 = get_bitrate(chunk_size, t0).round(0)
593
- set :transfer_bitrate, bitrate0
594
-
595
- # Update job info
596
- percent0 = (100.0 * @transfer_sent / @transfer_total).round(0)
597
- set :progress, percent0
598
-
599
- # Log progress
600
- stack = []
601
- stack << "#{percent0} %"
602
- stack << (Helpers.format_bytes @transfer_sent, "B")
603
- stack << (Helpers.format_bytes @transfer_total, "B")
604
- stack << (Helpers.format_bytes bitrate0, "bps")
605
- info "Job.ftp_transfer" + stack.map{|txt| ("%#{DEFAULT_LOGS_PIPE_LEN.to_i}s" % txt)}.join("\t")
606
-
607
- # Update time pointer
608
- t0 = Time.now
609
-
610
- # Notify if requested
611
- unless notify_after_sec.nil? || (notified_at + notify_after_sec > Time.now)
612
- notif_status = {
613
- progress: percent0,
614
- transfer_sent: @transfer_sent,
615
- transfer_total: @transfer_total,
616
- transfer_bitrate: bitrate0
617
- }
618
- client_notify :progress, status: notif_status
619
- notified_at = Time.now
620
- end
591
+ @ftp.putbinaryfile(source_filename, target_real, @chunk_size) do |block|
592
+ # Update the worker activity marker
593
+ worker_is_still_active
621
594
 
595
+ # Update job status after this block transfer
596
+ ftp_transfer_block block
622
597
  end
623
598
 
624
599
  # Rename temp file to target_temp
625
600
  if @tempfile
626
- newstatus :renaming
601
+ newstatus JOB_STATUS_RENAMING
627
602
  info "Job.ftp_transfer renaming: #{target_name}"
628
603
  @ftp.rename target_real, target_name
629
604
  end
630
605
 
631
606
  # Compute final bitrate
632
- set :transfer_bitrate, get_bitrate(@transfer_total, tstart).round(0)
607
+ set :transfer_bitrate, get_bitrate(@transfer_total, transfer_started_at).round(0)
633
608
 
634
609
  # Done
635
610
  set :source_current, nil
636
611
  info "Job.ftp_transfer finished"
637
612
  end
638
613
 
614
+ def ftp_transfer_block block
615
+ # Update counters
616
+ @transfer_sent += block.bytesize
617
+ set :transfer_sent, @transfer_sent
618
+
619
+ # Update bitrate
620
+ #dt = Time.now - t0
621
+ bitrate0 = get_bitrate(@chunk_size, @transfer_pointer_at).round(0)
622
+ set :transfer_bitrate, bitrate0
623
+
624
+ # Update job info
625
+ percent0 = (100.0 * @transfer_sent / @transfer_total).round(0)
626
+ set :progress, percent0
627
+
628
+ # Log progress
629
+ stack = []
630
+ stack << "#{percent0} %"
631
+ stack << (Helpers.format_bytes @transfer_sent, "B")
632
+ stack << (Helpers.format_bytes @transfer_total, "B")
633
+ stack << (Helpers.format_bytes bitrate0, "bps")
634
+ stack2 = stack.map{ |txt| ("%#{LOG_PIPE_LEN.to_i}s" % txt)}.join("\t")
635
+ info "Job.ftp_transfer #{stack2}"
636
+
637
+ # Update time pointer
638
+ @transfer_pointer_at = Time.now
639
+
640
+ # Notify if requested
641
+ # info "Job.ftp_transfer next notif (#{(@notified_at+@notify_after_sec).to_f}) now #{Time.now.to_f}"
642
+ if @notify_after_sec.nil? || (Time.now > @notified_at + @notify_after_sec)
643
+ notif_status = {
644
+ progress: percent0,
645
+ transfer_sent: @transfer_sent,
646
+ transfer_total: @transfer_total,
647
+ transfer_bitrate: bitrate0
648
+ }
649
+ client_notify :progress, status: notif_status
650
+ @notified_at = Time.now
651
+ end
652
+ end
653
+
639
654
  def client_notify event, payload = {}
640
655
  # Skip if no URL given
641
656
  return unless @notify
642
657
 
643
658
  # Ok, create a notification!
644
- begin
645
- payload[:id] = @id
646
- payload[:event] = event
647
- RestFtpDaemon::Notification.new @notify, payload
648
- rescue Exception => ex
649
- info "Job.client_notify EXCEPTION: #{ex.inspect}"
650
- end
651
- end
659
+ payload[:id] = @id
660
+ payload[:event] = event
661
+ RestFtpDaemon::Notification.new @notify, payload
662
+
663
+ rescue Exception => ex
664
+ info "Job.client_notify EXCEPTION: #{ex.inspect}"
665
+ end
652
666
 
653
667
  def get_bitrate total, last_timestamp
654
668
  8*total.to_f / (Time.now - last_timestamp)
655
669
  end
656
670
 
671
+ def worker_is_still_active
672
+ Thread.current.thread_variable_set :updted_at, Time.now
673
+ end
674
+
657
675
  def oops event, exception, error = nil, include_backtrace = false
658
676
  # Log this error
659
677
  error = exception.class if error.nil?
660
678
 
661
679
  message = "Job.oops event[#{event.to_s}] error[#{error.to_s}] ex[#{exception.class}] #{exception.message}"
662
680
  if include_backtrace
663
- info message, lines: exception.backtrace
681
+ info message, exception.backtrace
664
682
  else
665
683
  info message
666
684
  end
@@ -669,9 +687,9 @@ module RestFtpDaemon
669
687
  @ftp.close unless @ftp.nil? || @ftp.welcome.nil?
670
688
 
671
689
  # Update job's internal status
672
- newstatus :failed
690
+ newstatus JOB_STATUS_FAILED
673
691
  @error = error
674
- set :error_exception, exception.class
692
+ set :error_exception, exception.class.to_s
675
693
  set :error_message, exception.message
676
694
 
677
695
  # Build status stack