mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
ActionController::Live documentation in the guides.
I'm adding documentation to the action_controller_overview guide which should tell people how to stream arbitrary data.
This commit is contained in:
parent
4f8168ec58
commit
c2fc9f6080
1 changed files with 86 additions and 0 deletions
|
@ -907,6 +907,92 @@ Now the user can request to get a PDF version of a client just by adding ".pdf"
|
||||||
GET /clients/1.pdf
|
GET /clients/1.pdf
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Live Streaming of Arbitrary Data
|
||||||
|
|
||||||
|
Rails allows you to stream more than just files. In fact, you can stream anything
|
||||||
|
you would like in a response object. The `ActionController::Live` module allows
|
||||||
|
you to create a persistent connection with a browser. Using this module, you will
|
||||||
|
be able to send arbitrary data to the browser at specific points in time.
|
||||||
|
|
||||||
|
#### Incorporating Live Streaming
|
||||||
|
|
||||||
|
Including `ActionController::Live` inside of your controller class will provide
|
||||||
|
all actions inside of the controller the ability to stream data. You can mix in
|
||||||
|
the module like so:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class MyController < ActionController::Base
|
||||||
|
include ActionController::Live
|
||||||
|
|
||||||
|
def stream
|
||||||
|
response.headers['Content-Type'] = 'text/event-stream'
|
||||||
|
100.times {
|
||||||
|
response.stream.write "hello world\n"
|
||||||
|
sleep 1
|
||||||
|
}
|
||||||
|
ensure
|
||||||
|
response.stream.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
The above code will keep a persistent connection with the browser and send 100
|
||||||
|
messages of `"hello world\n"`, each one second apart.
|
||||||
|
|
||||||
|
There are a couple of things to notice in the above example. We need to make
|
||||||
|
sure to close the response stream. Forgetting to close the stream will leave
|
||||||
|
the socket open forever. We also have to set the content type to `text/event-stream`
|
||||||
|
before we write to the response stream. This is because headers cannot be written
|
||||||
|
after the response has been committed (when `response.committed` returns a truthy
|
||||||
|
value), which occurs when you `write` or `commit` the response stream.
|
||||||
|
|
||||||
|
#### Example Usage
|
||||||
|
|
||||||
|
Let's suppose that you were making a Karaoke machine and a user wants to get the
|
||||||
|
lyrics for a particular song. Each `Song` has a particular number of lines and
|
||||||
|
each line takes time `num_beats` to finish singing.
|
||||||
|
|
||||||
|
If we wanted to return the lyrics in Karaoke fashion (only sending the line when
|
||||||
|
the singer has finished the previous line), then we could use `ActionController::Live`
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
class LyricsController < ActionController::Base
|
||||||
|
include ActionController::Live
|
||||||
|
|
||||||
|
def show
|
||||||
|
response.headers['Content-Type'] = 'text/event-stream'
|
||||||
|
song = Song.find(params[:id])
|
||||||
|
|
||||||
|
song.each do |line|
|
||||||
|
response.stream.write line.lyrics
|
||||||
|
sleep line.num_beats
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
response.stream.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
The above code sends the next line only after the singer has completed the previous
|
||||||
|
line.
|
||||||
|
|
||||||
|
#### Streaming Considerations
|
||||||
|
|
||||||
|
Streaming arbitrary data is an extremely powerful tool. As shown in the previous
|
||||||
|
examples, you can choose when and what to send across a response stream. However,
|
||||||
|
you should also note the following things:
|
||||||
|
|
||||||
|
* Each response stream creates a new thread and copies over the thread local
|
||||||
|
variables from the original thread. Having too many thread local variables can
|
||||||
|
negatively impact performance. Similarly, a large number of threads can also
|
||||||
|
hinder performance.
|
||||||
|
* Failing to close the response stream will leave the corresponding socket open
|
||||||
|
forever. Make sure to call `close` whenever you are using a response stream.
|
||||||
|
* WEBrick servers buffer all responses, and so including `ActionController::Live`
|
||||||
|
will not work. You must use a web server which does not automatically buffer
|
||||||
|
responses.
|
||||||
|
|
||||||
Log Filtering
|
Log Filtering
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue