rest-ftp-daemon 0.101 → 0.103.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b3c42331f0e483617809300fcc7b6623e94e617b
4
- data.tar.gz: 0184e556177357a18e19a686d3fc3ae852dcbffd
3
+ metadata.gz: c059a568b0a22503a734c966807a19c8ff426333
4
+ data.tar.gz: a3d2443af653af100e642e86ba7144a2b9985495
5
5
  SHA512:
6
- metadata.gz: ead761e0002d4cfda4409fd43dd1c5828040b204fadb2286898c31ccd428edc41be0dd3c83a334d4c0c35770c5bd77856c3665279b539ca3614460990e5b78c6
7
- data.tar.gz: 0518b79a4037e122c99d6ce50e660724f1db21693c0e5abfeeab319f6759dfce66461aaf7bc999500e967f833c67660fbadfa6a00f241be65c6b154099021ab7
6
+ metadata.gz: 07afa716bc8b3b701377cfe1a9452e22238cc8e82af287f544e499cc2a4d263bd266e3d83f8a2aa53ca37381653d1fff961bdbff6bf9446167cf1276fb8bddf8
7
+ data.tar.gz: 31fb4ea27d1e64278563eb3e2e93375c24d1f9794e632acd7afbeb897dc0a6d88024fe2dd3c4393648fa151b1f54c35432323f45cd90b4f9d368feeb208078a1
data/README.md CHANGED
@@ -2,7 +2,7 @@ rest-ftp-daemon
2
2
  ====================================================================================
3
3
 
4
4
 
5
- This is a pretty simple FTP client daemon, controlled through a RESTfull API.
5
+ This is a pretty simple FTP client daemon, controlled through a RESTful API.
6
6
 
7
7
  API documentation is [maintained on Apiary](http://docs.restftpdaemon.apiary.io/)
8
8
 
@@ -6,11 +6,8 @@ module RestFtpDaemon
6
6
  # Job ID
7
7
  expose :id
8
8
 
9
- # Job specific attributes
10
- Job::FIELDS.each do |field|
11
- expose field
12
- #expose field, unless: lambda { |object, options| object.instance_variable_get("@#{field}").nil? }
13
- end
9
+ # Job specific attributes and flags
10
+ Job::FIELDS.each { |name| expose name }
14
11
 
15
12
  # Technical fields
16
13
  expose :wid, unless: lambda { |object, options| object.wid.nil? }
@@ -63,10 +63,13 @@ module RestFtpDaemon
63
63
  optional :label, type: String, desc: "Descriptive label for this job"
64
64
  optional :notify, type: String, desc: "URL to get POST'ed notifications back"
65
65
  optional :priority, type: Integer, desc: "Priority level of the job (lower is stronger)"
66
- optional :overwrite, type: Boolean, desc: "wether to overwrites files at target server",
67
- default: false
68
- optional :mkdir, type: Boolean, desc: "wether to create missing directories on target server",
69
- default: false
66
+
67
+ optional :overwrite, type: Boolean, desc: "overwrites files at target server",
68
+ default: Settings.transfer[:overwrite]
69
+ optional :mkdir, type: Boolean, desc: "create missing directories on target server",
70
+ default: Settings.transfer[:mkdir]
71
+ optional :tempfile, type: Boolean, desc: "upload to a temp file before renaming it to the target filename",
72
+ default: Settings.transfer[:tempfile]
70
73
  end
71
74
 
72
75
  post '/jobs/' do
@@ -95,7 +98,7 @@ module RestFtpDaemon
95
98
  api_error exception
96
99
  else
97
100
  status 201
98
- present job, :with => RestFtpDaemon::API::Entities::JobPresenter
101
+ present job, :with => RestFtpDaemon::API::Entities::JobPresenter, hide_params: true
99
102
  end
100
103
  end
101
104
 
@@ -1,11 +1,12 @@
1
1
  # Terrific constants
2
2
  APP_NAME = "rest-ftp-daemon"
3
- APP_VER = "0.101"
3
+ APP_VER = "0.103.1"
4
4
 
5
5
  # Some global constants
6
6
  IDENT_JOB_LEN = 4
7
7
  IDENT_NOTIF_LEN = 4
8
8
  IDENT_RANDOM_LEN = 8
9
+ IDENT_TEMPFILE_LEN = 8
9
10
  DEFAULT_LOGS_PIPE_LEN = 15
10
11
  DEFAULT_LOGS_ID_LEN = 8
11
12
 
@@ -6,35 +6,32 @@ require 'timeout'
6
6
  module RestFtpDaemon
7
7
  class Job
8
8
 
9
- FIELDS = [:source, :target, :label, :priority, :notify, :overwrite, :mkdir]
9
+ FIELDS = [:source, :target, :label, :priority, :notify, :overwrite, :mkdir, :tempfile]
10
10
 
11
- attr_reader :id
12
11
  attr_accessor :wid
13
12
 
13
+ attr_reader :id
14
14
  attr_reader :error
15
15
  attr_reader :status
16
16
 
17
17
  attr_reader :queued_at
18
18
  attr_reader :updated_at
19
-
20
19
  attr_reader :started_at
21
20
  attr_reader :finished_at
22
21
 
23
22
  attr_reader :params
24
23
 
25
- FIELDS.each do |field|
26
- attr_reader field
24
+ FIELDS.each do |name|
25
+ attr_reader name
27
26
  end
28
27
 
28
+
29
29
  def initialize job_id, params={}
30
30
  # Call super
31
31
  # super()
32
32
 
33
33
  # Init context
34
34
  @id = job_id.to_s
35
- FIELDS.each do |field|
36
- instance_variable_set("@#{field.to_s}", params[field])
37
- end
38
35
  @params = {}
39
36
  @updated_at = nil
40
37
  @started_at = nil
@@ -44,25 +41,30 @@ module RestFtpDaemon
44
41
  @wid = nil
45
42
 
46
43
  # Logger
47
- # @logger = RestFtpDaemon::Logger.new(:workers, "JOB #{id}")
48
44
  @logger = RestFtpDaemon::LoggerPool.instance.get :workers
49
45
 
50
46
  # Protect with a mutex
51
47
  @mutex = Mutex.new
52
48
 
49
+ # Import query params
50
+ FIELDS.each do |name|
51
+ instance_variable_set "@#{name.to_s}", params[name]
52
+ end
53
+
54
+ # Set super-default flags
55
+ flag_default :mkdir, false
56
+ flag_default :overwrite, false
57
+ flag_default :tempfile, false
58
+
53
59
  # Flag current job
54
60
  @queued_at = Time.now
55
61
  @status = :created
56
62
 
57
63
  # Send first notification
58
- #info "Job.initialize/notify"
59
64
  info "Job.initialized"
60
65
  client_notify "rftpd.queued"
61
66
  end
62
67
 
63
- def close
64
- end
65
-
66
68
  def process
67
69
  # Update job's status
68
70
  @error = nil
@@ -74,31 +76,31 @@ module RestFtpDaemon
74
76
  prepare
75
77
 
76
78
  rescue RestFtpDaemon::JobMissingAttribute => exception
77
- return oops "rftpd.started", exception, :job_missing_attribute
79
+ return oops "rftpd.started", exception, :missing_attribute
78
80
 
79
81
  # rescue RestFtpDaemon::JobSourceNotFound => exception
80
82
  # return oops "rftpd.started", exception, :job_source_not_found
81
83
 
82
84
  rescue RestFtpDaemon::JobUnresolvedTokens => exception
83
- return oops "rftpd.started", exception, :job_unresolved_tokens
85
+ return oops "rftpd.started", exception, :unresolved_tokens
84
86
 
85
87
  rescue RestFtpDaemon::JobTargetUnparseable => exception
86
- return oops "rftpd.started", exception, :job_target_unparseable
88
+ return oops "rftpd.started", exception, :target_unparseable
87
89
 
88
90
  rescue RestFtpDaemon::JobTargetUnsupported => exception
89
- return oops "rftpd.started", exception, :job_target_unsupported
91
+ return oops "rftpd.started", exception, :target_unsupported
92
+
93
+ rescue URI::InvalidURIError => exception
94
+ return oops "rftpd.started", exception, :target_invalid
90
95
 
91
96
  rescue RestFtpDaemon::JobAssertionFailed => exception
92
- return oops "rftpd.started", exception, :job_assertion_failed
97
+ return oops "rftpd.started", exception, :assertion_failed
93
98
 
94
99
  rescue RestFtpDaemon::RestFtpDaemonException => exception
95
- return oops "rftpd.started", exception, :job_prepare_failed
96
-
97
- rescue URI::InvalidURIError => exception
98
- return oops "rftpd.started", exception, :job_target_invalid
100
+ return oops "rftpd.started", exception, :prepare_failed
99
101
 
100
102
  rescue Exception => exception
101
- return oops "rftpd.started", exception, :job_prepare_unhandled, true
103
+ return oops "rftpd.started", exception, :prepare_unhandled, true
102
104
 
103
105
  else
104
106
  # Prepare done !
@@ -113,47 +115,47 @@ module RestFtpDaemon
113
115
  @status = :starting
114
116
  transfer
115
117
 
118
+ rescue SocketError => exception
119
+ return oops "rftpd.ended", exception, :conn_socket_error
120
+
116
121
  rescue Errno::EHOSTDOWN => exception
117
- return oops "rftpd.ended", exception, :job_host_is_down
122
+ return oops "rftpd.ended", exception, :conn_host_is_down
118
123
 
119
124
  rescue Errno::ENOTCONN => exception
120
- return oops "rftpd.ended", exception, :job_connexion_failed
125
+ return oops "rftpd.ended", exception, :conn_failed
121
126
 
122
127
  rescue Errno::ECONNREFUSED => exception
123
- return oops "rftpd.ended", exception, :job_connexion_refused
124
-
125
- rescue SocketError => exception
126
- return oops "rftpd.ended", exception, :job_socket_error
128
+ return oops "rftpd.ended", exception, :conn_refused
127
129
 
128
130
  rescue Timeout::Error, Errno::ETIMEDOUT => exception
129
- return oops "rftpd.ended", exception, :job_timeout
130
-
131
- rescue Net::FTPPermError => exception
132
- return oops "rftpd.ended", exception, :job_perm_error
131
+ return oops "rftpd.ended", exception, :conn_timeout
133
132
 
134
133
  rescue OpenSSL::SSL::SSLError => exception
135
- return oops "rftpd.ended", exception, :job_openssl_error
134
+ return oops "rftpd.ended", exception, :conn_openssl_error
135
+
136
+ rescue Net::FTPPermError => exception
137
+ return oops "rftpd.ended", exception, :perm_error
136
138
 
137
139
  rescue Errno::EMFILE => exception
138
- return oops "rftpd.ended", exception, :job_too_many_open_files
140
+ return oops "rftpd.ended", exception, :too_many_open_files
139
141
 
140
142
  rescue RestFtpDaemon::JobSourceNotFound => exception
141
- return oops "rftpd.ended", exception, :job_source_not_found
143
+ return oops "rftpd.ended", exception, :source_not_found
142
144
 
143
145
  rescue RestFtpDaemon::JobTargetFileExists => exception
144
- return oops "rftpd.ended", exception, :job_target_file_exists
146
+ return oops "rftpd.ended", exception, :target_file_exists
145
147
 
146
148
  rescue RestFtpDaemon::JobTargetShouldBeDirectory => exception
147
- return oops "rftpd.ended", exception, :job_target_should_be_directory
149
+ return oops "rftpd.ended", exception, :target_not_directory
148
150
 
149
151
  rescue RestFtpDaemon::JobAssertionFailed => exception
150
- return oops "rftpd.started", exception, :job_assertion_failed
152
+ return oops "rftpd.started", exception, :assertion_failed
151
153
 
152
154
  rescue RestFtpDaemon::RestFtpDaemonException => exception
153
- return oops "rftpd.ended", exception, :job_transfer_failed
155
+ return oops "rftpd.ended", exception, :transfer_failed
154
156
 
155
157
  rescue Exception => exception
156
- return oops "rftpd.ended", exception, :job_transfer_unhandled, true
158
+ return oops "rftpd.ended", exception, :transfer_unhandled, true
157
159
 
158
160
  else
159
161
  # All done !
@@ -187,19 +189,6 @@ module RestFtpDaemon
187
189
  (@finished_at - @started_at).round(2)
188
190
  end
189
191
 
190
- def wander time
191
- info "Job.wander #{time}"
192
- @wander_for = time
193
- @wander_started = Time.now
194
- sleep time
195
- info "Job.wandered ok"
196
- end
197
-
198
- def wandering_time
199
- return if @wander_started.nil? || @wander_for.nil?
200
- @wander_for.to_f - (Time.now - @wander_started)
201
- end
202
-
203
192
  def set attribute, value
204
193
  @mutex.synchronize do
205
194
  @params || {}
@@ -300,10 +289,11 @@ module RestFtpDaemon
300
289
  # Scheme-aware config
301
290
  ftp_init
302
291
 
303
- # Connect remote server, login and chdir
304
- ftp_connect_and_login
292
+ # Connect to remote server and login
293
+ ftp_connect
294
+ ftp_login
305
295
 
306
- # Connect remote server, login and chdir
296
+ # Change to the right path
307
297
  path = Helpers.extract_dirname(@target_url.path).to_s
308
298
  ftp_chdir_or_buildpath path
309
299
 
@@ -344,10 +334,10 @@ module RestFtpDaemon
344
334
  def oops signal_name, exception, error_name = nil, include_backtrace = false
345
335
  # Log this error
346
336
  error_name = exception.class if error_name.nil?
347
- info "Job.oops si[#{signal_name}] er[#{error_name.to_s}] ex[#{exception.class}]"
337
+ info "Job.oops si[#{signal_name}] er[#{error_name.to_s}] ex[#{exception.class}] #{exception.message}"
348
338
 
349
339
  # Close ftp connexion if open
350
- @ftp.close unless @ftp.nil?
340
+ @ftp.close unless @ftp.welcome.nil?
351
341
 
352
342
  # Update job's internal status
353
343
  @status = :failed
@@ -374,6 +364,17 @@ module RestFtpDaemon
374
364
  client_notify signal_name, error_name, notif_status
375
365
  end
376
366
 
367
+ def flag_default name, default
368
+ # build the flag instance var name
369
+ variable = "@#{name.to_s}"
370
+
371
+ # If it's true or false, that's ok
372
+ return if [true, false].include? instance_variable_get(variable)
373
+
374
+ # Otherwise, set it to the default value
375
+ instance_variable_set variable, default
376
+ end
377
+
377
378
  def ftp_init
378
379
  # Method assertions
379
380
  info "Job.ftp_init asserts"
@@ -398,19 +399,20 @@ module RestFtpDaemon
398
399
  @ftp.passive = true
399
400
  end
400
401
 
401
- def ftp_connect_and_login
402
- #@status = :ftp_connect
403
- # connect_timeout_sec = (Settings.transfer.connect_timeout_sec rescue nil) || DEFAULT_CONNECT_TIMEOUT_SEC
404
-
405
- # Method assertions
406
- host = @target_url.host
407
- info "Job.ftp_connect connect [#{host}]"
402
+ def ftp_connect
408
403
  @status = :ftp_connect
404
+ host = @target_url.host
405
+ info "Job.ftp_connect [#{host}]"
409
406
  raise RestFtpDaemon::JobAssertionFailed if @ftp.nil? || @target_url.nil?
407
+
410
408
  @ftp.connect(host)
409
+ end
411
410
 
411
+ def ftp_login
412
412
  @status = :ftp_login
413
- info "Job.ftp_connect login [#{@target_url.user}]"
413
+ info "Job.ftp_login [#{@target_url.user}]"
414
+ raise RestFtpDaemon::JobAssertionFailed if @ftp.nil? || @target_url.user.nil? || @target_url.password.nil?
415
+
414
416
  @ftp.login @target_url.user, @target_url.password
415
417
  end
416
418
 
@@ -504,7 +506,6 @@ module RestFtpDaemon
504
506
  else
505
507
  # won't overwrite then stop here
506
508
  info "Job.ftp_transfer failed: target file exists"
507
- @ftp.close
508
509
  raise RestFtpDaemon::JobTargetFileExists
509
510
  end
510
511
  end
@@ -513,12 +514,19 @@ module RestFtpDaemon
513
514
  update_every_kb = (Settings.transfer.update_every_kb rescue nil) || DEFAULT_UPDATE_EVERY_KB
514
515
  notify_after_sec = Settings.transfer.notify_after_sec rescue nil
515
516
 
517
+ # Compute temp target name
518
+ target_real = target_name
519
+ if @tempfile
520
+ target_real = "#{target_name}.#{Helpers.identifier(IDENT_TEMPFILE_LEN)}-temp"
521
+ info "Job.ftp_transfer target_real [#{target_real}]"
522
+ end
523
+
516
524
  # Start transfer
517
525
  chunk_size = update_every_kb * 1024
518
526
  t0 = tstart = Time.now
519
527
  notified_at = Time.now
520
528
  @status = :uploading
521
- @ftp.putbinaryfile(source_match, target_name, chunk_size) do |block|
529
+ @ftp.putbinaryfile(source_match, target_real, chunk_size) do |block|
522
530
  # Update counters
523
531
  @transfer_sent += block.bytesize
524
532
  set :transfer_sent, @transfer_sent
@@ -544,6 +552,8 @@ module RestFtpDaemon
544
552
  t0 = Time.now
545
553
 
546
554
  # Notify if requested
555
+ @status = :uploaded
556
+ info "Job.ftp_transfer uploaded"
547
557
  unless notify_after_sec.nil? || (notified_at + notify_after_sec > Time.now)
548
558
  notif_status = {
549
559
  progress: percent1,
@@ -557,6 +567,13 @@ module RestFtpDaemon
557
567
 
558
568
  end
559
569
 
570
+ # Rename temp file to target_temp
571
+ if @tempfile
572
+ @status = :renaming
573
+ info "Job.ftp_transfer renaming to #{target_name}"
574
+ @ftp.rename target_real, target_name
575
+ end
576
+
560
577
  # Compute final bitrate
561
578
  set :transfer_bitrate, get_bitrate(@transfer_total, tstart).round(0)
562
579
 
@@ -39,14 +39,14 @@ module RestFtpDaemon
39
39
  # Wait for a job to come into the queue
40
40
  worker_status wid, :waiting
41
41
  job = $queue.pop
42
- info "worker [#{wid}] popped [#{job.id}]"
43
42
 
44
43
  # Do the job
44
+ info "worker [#{wid}] processing [#{job.id}]"
45
45
  worker_status wid, :processing, job.id
46
46
  job.wid = wid
47
47
  job.process
48
48
  info "worker [#{wid}] processed [#{job.id}]"
49
- job.close
49
+ # job.close
50
50
  worker_status wid, :done
51
51
 
52
52
  # Increment total processed jobs count
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.date = Time.now.strftime("%Y-%m-%d")
11
11
  spec.authors = ["Bruno MEDICI"]
12
12
  spec.email = "rest-ftp-daemon@bmconseil.com"
13
- spec.description = "This is a pretty simple FTP client daemon, controlled through a RESTfull API"
13
+ spec.description = "This is a pretty simple FTP client daemon, controlled through a RESTful API"
14
14
  spec.summary = "RESTful FTP client daemon"
15
15
  spec.homepage = "http://github.com/bmedici/rest-ftp-daemon"
16
16
  spec.licenses = ["MIT"]
@@ -11,6 +11,11 @@ defaults: &defaults
11
11
  update_every_kb: 1024
12
12
  notify_after_sec: 10
13
13
 
14
+ mkdir: true
15
+ tempfile: true
16
+ overwrite: false
17
+
18
+
14
19
  conchita:
15
20
  timer: 10
16
21
  #clean_failed: 3600
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.101'
4
+ version: 0.103.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bruno MEDICI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-24 00:00:00.000000000 Z
11
+ date: 2015-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -178,7 +178,7 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- description: This is a pretty simple FTP client daemon, controlled through a RESTfull
181
+ description: This is a pretty simple FTP client daemon, controlled through a RESTful
182
182
  API
183
183
  email: rest-ftp-daemon@bmconseil.com
184
184
  executables: