Подробнее здесь.
Несколько косяков.
1. Нужен сервер с поддержкой SSE. В моем случае это Puma.
2. Если не включить config.cache_classes = true и config.eager_load = true, то работать не будет, будет вечное ожидание отработки контроллера вызываемого через events.
P.S. Эта проблема решается включением опции Just add config.allow_concurrency = true to your development.rb.
3. При включении опций, указанных выше, есть проблема с автоматической подгрузкой измененного кода. Нужно останавливать вебсервер и заново его запускать, что, конечно, замедляет разработку.
Мои эксперименты закончились вот таким небольшим контроллером:
class Api::EventsController < ApplicationController
include ActionController::Live
skip_before_filter :authenticate_account!, only: [:index]
def index
response.headers["Content-Type"] = "text/event-stream"
redis = Redis.new
redis.psubscribe('tickets.*') do |on|
on.pmessage do |pattern, event, data|
response.stream.write "event: #{event}\n"
response.stream.write "data: #{data}\n\n"
end
end
rescue IOError
logger.info "stream closed"
ensure
redis.quit
response.stream.close
end
end
Несколько косяков.
1. Нужен сервер с поддержкой SSE. В моем случае это Puma.
2. Если не включить config.cache_classes = true и config.eager_load = true, то работать не будет, будет вечное ожидание отработки контроллера вызываемого через events.
P.S. Эта проблема решается включением опции Just add config.allow_concurrency = true to your development.rb.
3. При включении опций, указанных выше, есть проблема с автоматической подгрузкой измененного кода. Нужно останавливать вебсервер и заново его запускать, что, конечно, замедляет разработку.
Мои эксперименты закончились вот таким небольшим контроллером:
class Api::EventsController < ApplicationController
include ActionController::Live
skip_before_filter :authenticate_account!, only: [:index]
def index
response.headers["Content-Type"] = "text/event-stream"
redis = Redis.new
redis.psubscribe('tickets.*') do |on|
on.pmessage do |pattern, event, data|
response.stream.write "event: #{event}\n"
response.stream.write "data: #{data}\n\n"
end
end
rescue IOError
logger.info "stream closed"
ensure
redis.quit
response.stream.close
end
end
И в модели ticket.rb я добавил такие хуки
after_create :notify_create
after_destroy :notify_destroy
def notify_destroy
$redis.publish('tickets.destroy', self.to_json)
end
def notify_create
$redis.publish('tickets.create', self.to_json)
end
В Javascript (Coffeescript) я делаю примерно следующее:
@source = new EventSource("/api/events")
source.addEventListener 'tickets.create', (e) =>
jQuery.gritter.add
title: 'Новый тикет'
text: "Добравлен тикет"
console.log "pushed ticket"
@tickets.push(new Ticket($.parseJSON(e.data)))
source.addEventListener 'tickets.destroy', (e) =>
data = $.parseJSON(e.data)
@tickets.remove (item) => item for item in @tickets() when item.id is data.id
Комментариев нет:
Отправить комментарий