2013-10-31 35 views
0

要描述我的問題,我附上簡單的抽筋http://cramp.in/類。 我加入一些修改,但其主要的工作就像https://github.com/lifo/cramp-pub-sub-chat-demo/blob/master/app/actions/chat_action.rb抽筋框架同步「渲染」正確的方式使用EM同步

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 defferable反應,大概。 所以我嘗試這種方式同步的:

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內嵌同步的好方法嗎?
  • 有更好,更清晰的方式來處理它嗎?

謝謝!

回答

0

我發現這個問題的解決方案,EM-同步應該通過要求該圖書館內聯工作開箱:

require 'em-synchrony/em-hiredis' 

class ChatAction < Cramp::Websocket 

使用EM :: Synchrony.next_tick塊是壞主意,用EM的很大的幫助-synchrony社區我添加em-hiredis 0.2.1 compatibility patch on github

所以現在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' 

希望它能幫助別人。