2

How to handle Ruby Net::SFTP transfer interruption like network disconnection?

When I run my example code and the network is disconnected during the transfer, application stays running.

require 'net/sftp'

Net::SFTP.start("testing","root",:timeout=>1) do |sftp|
    begin
        sftp.download!("testfile_100MB", "testfile_100MB")
    rescue RuntimeError =>e
        puts e.message
    end
end
matejuh
  • 396
  • 4
  • 13
  • In a situation when your program is invoked as a script this is rarely a problem, net::sftp has default timeout, but it is for the initial phase of the connection, I think. so, if the established connection hangs you need to interrupt it from the parent thread, or another process (nanny). Probably the easiest way to go around this problem. If you have a long running application than threading is the best way to solve this. – Istvan Nov 22 '12 at 07:09

2 Answers2

4

You can create another thread to watch the downloading progress and crash the application if the download appears unresponsive. Since Net::SFTP allows you to pass in a custom handler to the download! method, you can set up the watcher thread like this:

class CustomHandler
  def extend_time
    @crash_time = Time.now + 30
  end

  # called when downloading has started
  def on_open(downloader, file)
    extend_time
    downloader_thread = Thread.current
    @watcher_thread = Thread.new{
      while true do
        if Time.now > @crash_time
          downloader_thread.raise "Downloading appears unresponsive. Network disconnected?"
        end
        sleep 5
      end
    }
  end

  # called when new bytes are downloaded
  def on_get(downloader, file, offset, data)
    extend_time
  end

  # called when downloading is completed
  def on_close(downloader, file)
    @watcher_thread.exit
  end
end

And don't forget to pass in the custom handler like this:

sftp.download!(remote_path, local_path, :progress => CustomHandler.new)
042e
  • 307
  • 2
  • 5
0

The Net-SFTP class is dependant on the Net-SSH class for the underlying connection. In the example above the SSH connection attempts to maintain itself, hence the code continues to execute until deemed to have failed by SSH. The :timeout parameter only applies to the initial connection.

Sasha
  • 485
  • 3
  • 6