[~/sinatra/sinatra-streaming/sinatra-streaming-example(master)]$ cat web.rb require 'redis' require 'sinatra' configure do redis_url = ENV["REDISTOGO_URL"] || "redis://localhost:6379" uri = URI.parse(redis_url) set :redis, Redis.new(:host => uri.host, :port => uri.port, :password => uri.password) end get '/' do "<pre>curl -v https://sinatra-streaming-example.herokuapp.com/stream</pre>" end get '/stream' do puts "connection made" stream do |out| settings.redis.subscribe 'time' do |on| on.message do |channel, message| out << "#{message}\n" end end end endRedis is a key-value store; it supports lists, hashes, sets, and ordered sets.
El código
redis_url = ENV["REDISTOGO_URL"] || "redis://localhost:6379"decide si estamos en Heroku o no. Si estamos en Heroku deberemos haber instalado el Heroku addon Redis To Go.
La llamada:
set :redis, Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)conecta con el servidor Redis.
The Redis class exports methods that are named identical to the commands they execute. The arguments these methods accept are often identical to the arguments specified on the Redis website.
In Redis,
SUBSCRIBE
, UNSUBSCRIBE
and PUBLISH
implement
the Publish/Subscribe
messaging paradigm where
foo
and bar
the
client issues a SUBSCRIBE
providing the names of the channels:
SUBSCRIBE foo bar
Messages sent by other clients to these channels will be pushed by Redis to all the subscribed clients.
A client subscribed to one or more channels should not issue commands, although it can subscribe and unsubscribe to and from other channels.
The reply of the SUBSCRIBE
and UNSUBSCRIBE
operations are sent in
the form of messages, so that the client can just read a coherent
stream of messages where the first element indicates the type of
message.
El objeto on
pasado al bloque está en la clase
Redis::Subscription:
settings.redis.subscribe 'time' do |on| on.message do |channel, message| out << "#{message}\n" endel objeto
on
dispone del método message
que
establece una callback
que será ejecutada cada vez que se produzca un mensaje.
[~/sinatra/sinatra-streaming/sinatra-streaming-example(master)]$ cat worker.rb require 'uri' require 'redis' redis_url = ENV["REDISTOGO_URL"] || "redis://localhost:6379" uri = URI.parse(redis_url) r = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password) while true do puts "publishing..." r.publish "time", Time.now.utc sleep 1 end
[~/sinatra/sinatra-streaming/sinatra-streaming-example(master)]$ cat Procfile web: bundle exec ruby web.rb -p $PORT worker: bundle exec ruby worker.rbThe
web
process type, describes to Heroku how to start the web application server.
An interesting thing to mention here is that Heroku
only auto-launches
the web process in your Procfile when deploying, whereas foreman
launches everything.
[~/sinatra/sinatra-streaming/sinatra-streaming-example(master)]$ cat Gemfile source 'https://rubygems.org' gem 'foreman' gem 'redis' gem 'sinatra' gem 'thin'
[~/sinatra/sinatra-streaming/sinatra-streaming-example(master)]$ redis-server [5604] 04 Dec 10:18:58.126 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf [5604] 04 Dec 10:18:58.129 * Max number of open files set to 10032 _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 2.6.14 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in stand alone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 5604 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' [5604] 04 Dec 10:18:58.129 # Server started, Redis version 2.6.14 [5604] 04 Dec 10:18:58.129 * The server is now ready to accept connections on port 6379
bundle exec foreman start
arranca tanto a worker
como
a web
:
[~/sinatra/sinatra-streaming/sinatra-streaming-example(master)]$ bundle exec foreman start 10:19:04 web.1 | started with pid 5606 10:19:04 worker.1 | started with pid 5607 10:19:05 worker.1 | publishing... 10:19:06 web.1 | == Sinatra/1.3.0 has taken the stage on 5000 for development with backup from Thin 10:19:06 web.1 | >> Thin web server (v1.2.11 codename Bat-Shit Crazy) 10:19:06 web.1 | >> Maximum connections set to 1024 10:19:06 web.1 | >> Listening on 0.0.0.0:5000, CTRL+C to stop 10:19:06 worker.1 | publishing... 10:19:07 worker.1 | publishing... 10:19:08 worker.1 | publishing... .................................. 10:19:37 worker.1 | publishing... 10:19:38 web.1 | connection made 10:19:39 worker.1 | publishing... ..................................
[~/sinatra/sinatra-streaming/sinatra-streaming-example(master)]$ curl -v http://localhost:5000/stream * Adding handle: conn: 0x7fc71280aa00 * Adding handle: send: 0 * Adding handle: recv: 0 * Curl_addHandleToPipeline: length: 1 * - Conn 0 (0x7fc71280aa00) send_pipe: 1, recv_pipe: 0 * About to connect() to localhost port 5000 (#0) * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 5000 (#0) > GET /stream HTTP/1.1 > User-Agent: curl/7.30.0 > Host: localhost:5000 > Accept: */* > < HTTP/1.1 200 OK < X-Frame-Options: sameorigin < X-XSS-Protection: 1; mode=block < Content-Type: text/html;charset=utf-8 < Connection: close * Server thin 1.2.11 codename Bat-Shit Crazy is not blacklisted < Server: thin 1.2.11 codename Bat-Shit Crazy < 2013-12-04 13:24:13 UTC 2013-12-04 13:24:14 UTC 2013-12-04 13:24:15 UTC 2013-12-04 13:24:16 UTC 2013-12-04 13:24:17 UTC .......................