簡體   English   中英

抽筋框架使用em-synchrony同步“渲染”正確方法

[英]cramp framework sync 'render' correct way using em-synchrony

為了描述我的問題,我附上了簡單的Cramp http://cramp.in/類。 我添加了一些修改,但其主要工作如https://github.com/lifo/cramp-pub-sub-chat-demo/blob/master/app/actions/chat_action.rb

class ChatAction < Cramp::Websocket

  use_fiber_pool

  on_start :create_redis
  on_finish :handle_leave, :destroy_redis
  on_data :received_data

  def create_redis
    @redis = EM::Hiredis.connect('redis://127.0.0.1:6379/0')    
  end

  def destroy_redis
    @redis.pubsub.close_connection
    @redis.close_connection
  end

  def received_data(data)
    msg = parse_json(data)
    case msg[:action]
    when 'join'
      handle_join(msg)
    when 'message'
      handle_message(msg)
    else
      # skip
    end
  end

  def handle_join(msg)
    @user = msg[:user]
    subscribe
    publish(:action => 'control', :user => @user, :message => 'joined the chat room')
  end

  def handle_leave
    publish :action => 'control', :user => @user, :message => 'left the chat room'
  end

  def handle_message(msg)
    publish(msg.merge(:user => @user))
    # added only for inline sync tests
    render_json(:action => 'message', :user => @user, :message => "this info should appear after published message")
  end

  private

  def subscribe
    @redis.pubsub.subscribe('chat') do |message|
      render(message)
    end
  end

  def publish(message)
    @redis.publish('chat', encode_json(message))
  end

  def encode_json(obj)
    Yajl::Encoder.encode(obj)
  end

  def parse_json(str)
    Yajl::Parser.parse(str, :symbolize_keys => true)
  end

  def render_json(hash)
    render encode_json(hash)
  end
end

關於我嘗試執行的操作的更多信息是handle_message方法。

我嘗試以正確的順序向客戶端發送消息。 第一次向所有訂閱者發布消息,第二次僅針對當前連接的客戶端呈現一些內部信息。

對於以上代碼,客戶端收到:

{"action":"message","user":"user1","message":"this info should appear after published message"}
{"action":"message","message":"simple message","user":"user1"}

由於em-hiredis的響應不同,它可能不同步。 所以我嘗試以這種方式同步它:

def handle_message(msg)
  EM::Synchrony.sync publish(msg.merge(:user => @user))
  EM::Synchrony.next_tick do # if I comment this block messages order is still incorrect
     render_json(:action => 'message', :user => @user, :message => "this info should appear after published message")
  end
end

現在,客戶端以正確的順序處理消息。

{"action":"message","message":"simple message","user":"user1"}
{"action":"message","user":"user1","message":"this info should appear after published message"}

我的問題是:

  • 當我評論EM :: Synchrony.next_tick塊時,消息順序仍然不正確。 在此示例中,EM :: Synchrony.next_tick塊具有什么含義?
  • 這是與Cramp或EventMachine處理內聯同步的好方法嗎?
  • 有沒有更好,更清晰的方法來處理它?

謝謝!

我發現了此問題的解決方案,em-synchrony應通過要求以下庫立即內聯工作:

require 'em-synchrony/em-hiredis'

class ChatAction < Cramp::Websocket

使用EM :: Synchrony.next_tick塊是個壞主意,在em-synchrony社區的大力幫助下,我在github上添加了em-hiredis 0.2.1兼容性補丁。

所以現在handle_message方法看起來像這樣:

def handle_message(msg)
   publish(msg.merge(:user => @user))
   render_json(:action => 'message', :user => @user, :message => "this info should appear after published message")
end

不要忘記從github上獲取這個寶石

gem 'em-synchrony', :git=> 'git://github.com/igrigorik/em-synchrony.git'

希望它可以幫助某人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM