To “send data to the browser immediately”, you need to use one of three strategies:
- Short survey
- Streaming
- Long survey
(in the following examples, I assume $logs is of type Queue
Short survey
A short survey is a classic way to receive pending information from a server. This means that once every X seconds the client asks the server “do you have new information?”, The server answers either “no”, and in this case the client returns for another X seconds, or the server answers “yes”, here some new information ... "which the client can then display before sleeping for another X seconds.
The main drawback of this strategy is that it is supported by all browsers and all ruby versions (simple AJAX calls).
The disadvantage of this strategy is that before you receive new data, you will have a delay of up to X seconds. If X is too short, you will suffer from a lot of network overhead (all requests with empty answers).
Implementation Example:
def get_logs available_logs = [] while(line = $logs.pop(true) rescue nil) available_logs << line body available_logs.join($/) end
Streaming
A streaming strategy is when your client opens a request to the server, the server starts sending a response to the client, but when the available information ends, it does not close the connection, but leaves it open. Then it continues to receive information about the stream in the open socket as information arrives.
Rails 4.0 has an ActionController :: Live that implements this strategy. For Rails 3.2, you can try looking at this answer: fooobar.com/questions/120897 / ...
Implementation Example:
def get_logs class LogConsumer def each while $channel.active? yield $logs.pop + $/ end end end self.response_body = LogConsumer.new end
The main difference between this solution and the other two is that the client implementation is not so direct - the client cannot just wait for a response to return and then display it (for example, using jQuery by default). To implement the example, many places point to Ajax Patterns , which are currently unavailable: - (.
Another option I've seen is to use the portal plugin *:
portal.open("/get_logs", { inbound: function(data) { render_log_lines(data); } });
* I have no experience using this plugin, so this should be considered as a research area, and not as a working example ...
Long survey
Long polling means your AJAX client is requesting a server for the next line of the log. If the server has one (or more) to provide, it returns it to the client, the client displays the rows (rows) and requests again. If the server does not have a string to provide, it does not return an empty response, but rather hangs with the request and waits until the line is available. As soon as a new line appears, it is returned to the client. The client displays a string and then immediately requests the server.
When choosing this strategy, you must make sure that there is not a single timeout on the web server or client, or at other points in the middle (load balancers, etc.)
Implementation Example:
def get_logs available_logs = [] while(line = $logs.pop(true) rescue nil) available_logs << line if available_logs.empty? available_logs << $logs.pop end body available_logs.join($/) end