Blog Post: Elixir FTP Client: GenServer - Part 1

Learn how to leverage Erlang + Elixir’s GenServer to build a robust FTP Client.

4 Likes

Well put! The only thing that bugs me is this code would suffer crashes operating against slow ftp servers. The code below would blow up if there is no response for :ftp.ls/0 is 5 seconds.

def ls do
  GenServer.call({:global, __MODULE__}, :ls)
end

I would probably put a greater timeout or even :infinity there.

Damn, this is like a blast from the past. We were using ftp for one of our projects back in the day, nasty stuff when it stops working silently.

The approach we took back then was to check for files every 1 minute. What we did differently was that we would establish a new connection every-time and close when done, this builds a layer of fault-tolerance because we were interacting with different ftp servers, different versions and OS, and sometimes they would start behaving weirdly for no reason.

Thanks!!

Uff this is a hard one because it can block the calling process infinity.

Were you able to use mode: :active during that time? I’ve done some experiments but can’t get the active mode to work (receiving data as messages).

No, we were strictly using passive mode, it would be extremely annoying to set the infrastructure to allow incoming connections.

We did have an issue where data transfer would not work. There was a misconfigured ftp server behind a proxy that would send its local IP for data connections, but send the correct public one for commands, so it would work until you wanted to make file transfers. What I ended up doing was to extract the ftp library from OTP, mass rename it and change the library to always fetch the IP from the initial command connection for data connections.

I don’t remember exactly how I found out the exact issue, but I think it was by running ftp in verbose mode, it literally shows all the steps it takes if I remember correctly.

1 Like