Note that there are some explanatory texts on larger screens.

plurals
  1. PORuby Net::FTP Timeout Threads
    primarykey
    data
    text
    <p>I was trying to speed up multiple FTP downloads by using threaded FTP connections. My problem is that I always have threads hang. I am looking for a clean way of either telling FTP it needs to retry the ftp transaction, or at least knowing when the FTP connection is hanging.</p> <p>In the code below I am threading 5/6 separate FTP connections where each thread has a list of files it is expected to download. When the script completes, a few of the threads hang and can not be joined. I am using the variable @last_updated to represent the last successful download time. If the current time + 20 seconds exceeds @last_updated, kill the remaining threads. Is there a better way?</p> <pre><code>threads = [] max_thread_pool = 5 running_threads = 0 Thread.abort_on_exception = true existing_file_count = 0 files_downloaded = 0 errors = [] missing_on_the_server = [] @last_updated = Time.now if ids.length &gt; 0 ids.each_slice(ids.length / max_thread_pool) do |id_set| threads &lt;&lt; Thread.new(id_set) do |t_id_set| running_threads += 1 thread_num = running_threads thread_num.freeze puts "making thread # #{thread_num}" begin ftp = Net::FTP.open(@remote_site) ftp.login(@remote_user, @remote_password) ftp.binary = true #ftp.debug_mode = true ftp.passive = false rescue raise "Could not establish FTP connection" end t_id_set.each do |id| @last_updated = Time.now rmls_path = "/_Photos/0#{id[0,2]}00000/#{id[2,1]}0000/#{id[3,1]}000/#{id}-1.jpg" local_path = "#{@photos_path}/01/#{id}-1.jpg" progress += 1 unless File.exist?(local_path) begin ftp.getbinaryfile(rmls_path, local_path) puts "ftp reponse: #{ftp.last_response}" # find the percentage of progress just for fun files_downloaded += 1 p = sprintf("%.2f", ((progress.to_f / total) * 100)) puts "Thread # #{thread_num} &gt; %#{p} &gt; #{progress}/#{total} &gt; Got file: #{local_path}" rescue errors &lt;&lt; "#{thread_num} unable to get file &gt; ftp response: #{ftp.last_response}" puts errors.last if ftp.last_response_code.to_i == 550 # Add the missing file to the missing list missing_on_the_server &lt;&lt; errors.last.match(/\d{5,}-\d{1,2}\.jpg/)[0] end end else puts "found file: #{local_path}" existing_file_count += 1 end end puts "closing FTP connection #{thread_num}" ftp.close end # close thread end end # If @last_updated has not been updated on the server in over 20 seconds, wait 3 seconds and check again while Time.now &lt; @last_updated + 20 do sleep 3 end # threads are hanging so joining the threads does not work. threads.each { |t| t.kill } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload