1

Я пытаюсь использовать прямой эфир в Rails 4.0.1 в одном проекте, но я вижу проблемы ...ActionController :: Жить с SSE не работает должным образом

У меня есть это действие:

def realtime_push 
    response.headers['Content-Type'] = 'text/event-stream' 

    sse = SSE.new(response.stream) 

    d = Domain.find(params[:domain_id]) 

    begin 
     loop do 
     backlinks = d.backlinks.page(params[:page]).per(10) 
     pagination = render_to_string(:partial => 'backlinks/pagination', :layout => false, :locals => { :backlinks => backlinks }) 
     sse.write({ :html => pagination }, :event => 'pagination') 
     sleep 1 
     end 
    rescue IOError 
     # When the client disconnects, we'll get an IOError on write 
     logger.debug "DISCONNECTED" 
    ensure 
     sse.close 
    end 
end 

Когда я начинаю Puma и попытаться получить обновление:

curl http://localhost:3000/domains/16/backlinks/realtime_push 

Керл немедленно возвращается без выхода.

Curl заголовки:

HTTP/1.1 200 OK 
X-Frame-Options: SAMEORIGIN 
X-XSS-Protection: 1; mode=block 
X-Content-Type-Options: nosniff 
X-UA-Compatible: chrome=1 
Content-Type: text/event-stream 
Cache-Control: no-cache 
X-Request-Id: 1a07be2f-de8d-4ca8-87d0-eee2787ea649 
X-Runtime: 0.250782 
Transfer-Encoding: chunked 

и бревенчатые Puma показывает:

Started GET "/domains/16/backlinks/realtime_push" for 127.0.0.1 at 2013-11-08 12:22:30 +0100 
    ActiveRecord::SchemaMigration Load (0.7ms) SELECT "schema_migrations".* FROM "schema_migrations" 
Processing by BacklinksController#realtime_push as */* 
    Parameters: {"domain_id"=>"16"} 
    Domain Load (1.9ms) SELECT "domains".* FROM "domains" WHERE "domains"."id" = $1 LIMIT 1 [["id", "16"]] 
    (3.3ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] 
    Rendered backlinks/_pagination.haml (60.6ms) 
    (0.6ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] 
    Rendered backlinks/_pagination.haml (36.0ms) 
    (0.8ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] 
    Rendered backlinks/_pagination.haml (37.5ms) 
    (0.8ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] 
    Rendered backlinks/_pagination.haml (35.6ms) 
    (0.7ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] 
    Rendered backlinks/_pagination.haml (38.7ms) 
    (0.7ms) SELECT COUNT(*) FROM "backlinks" WHERE "backlinks"."domain_id" = $1 [["domain_id", 16]] 
    Rendered backlinks/_pagination.haml (37.0ms) 

Так что эти вещи странно:

  • локон не дал никакого вывода
  • журнала говорит, что он оказал пагинацию 6 раз
  • не было сообщения «DISCONNECT» в журнале

Любые идеи? Если я закомментировать две строки выше sse.write и вернуть текст вместо содержимого постраничной, он работает ...

Вот класс SSE:

class SSE 
    def initialize io 
    @io = io 
    end 

    def write object, options = {} 
    options.each do |k,v| 
     @io.write "#{k}: #{v}\n" 
    end 
    @io.write "data: #{JSON.dump(object)}\n\n" 
    end 

    def close 
    @io.close 
    end 
end 
+1

Что такое класс SSE? Он обрабатывает основную операцию в этом действии, и все же вы решили не делиться ею с нами. Что такое заголовки HTTP, когда вы вызываете завиток с '-i'? Является ли «Transfer-encoding» установленным «chunked»? Вы уверены, что начали Puma как веб-сервер, а не WEBrick? – mislav

+0

SSE-класс такой же, как в статье «Это живая» .. и код работает, когда я возвращаю простой текст и прокомментирую две строки выше sse.write .. как только я раскомментирую их, хотя я звоню sse.write точно так же, он перестает отправлять данные .. странно ... Я добавил заголовки скручиваний на почту ... Да, я уверен, что это Пума ... – davidhq

ответ

1

Это ошибка в render_to_string.

обезьяны патч, чтобы исправить это (, что на самом деле не решает проблему - см ниже):

def render_to_string(*) 
    orig_stream = response.stream 
    super 
ensure 
    if orig_stream 
    response.instance_variable_set(:@stream, orig_stream) 
    end 
end 

Источник: http://blog.sorah.jp/2013/07/28/render_to_string-in-ac-live

UPDATE: это только появляется, чтобы исправить эту проблему ... хотя это приведет к тому, что контроллер фактически отправит данные, принимающая сторона в JavaScript по какой-то причине все равно не получит уведомления о событиях, см. здесь: SSE (Server-sent events) not working

Смежные вопросы