[英]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應通過要求以下庫立即內聯工作:
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.