从 rails runner 内部触发/订阅 websocket-rails 事件

Posted

技术标签:

【中文标题】从 rails runner 内部触发/订阅 websocket-rails 事件【英文标题】:Trigger/Subscribe to websocket-rails event from inside a rails runner 【发布时间】:2015-06-27 00:10:20 【问题描述】:

我有一个带有 websocket-rails gem 的 Rails 应用程序。

在我的应用程序中有一个守护进程,我使用 rails runner MyDaemon.start 启动它

我正在使用websocket-rails Synchronization,所以我的config/initializers/websocket_rails.rb 看起来像这样:

WebsocketRails.setup do |config|
  config.log_internal_events = false
  config.standalone = false
  config.synchronize = true
end

MyDaemon 内部,使用同步,我可以触发将同时到达我的WebsocketRails::BaseController 和我的javascript WebSocketRails 的事件。

我正在尝试做的是找到一种方法来绑定我的MyDaemon 中的事件。

我尝试使用faye-websocket-ruby 和websocket-client-simple 来实现一个普通的WebSocket 客户端,但是在我的头在键盘上敲了一段时间之后,我发现有某种使用@ 的“握手”过程来自client_connected 消息的987654334@。 this other so question 中提供的解决方案基本上都不适合我。

我需要了解在我的MyDaemon 中是否可以直接订阅一些WebsocketRails 回调,甚至在EventMachine 中,或者我应该如何在Ruby 本身中实现Websocket 客户端。

我最后一次尝试使用 ruby​​ 客户端可以在 this gist 中找到,这是一个示例输出:

ruby client.rb ws://localhost:3000/websocket
[:open, "upgrade"=>"websocket", "connection"=>"Upgrade", "sec-websocket-accept"=>"zNTdGvxFKJeP+1PyGf27T4x2PGo="]

JSON message is
[["client_connected", "id"=>nil, "channel"=>nil, "user_id"=>nil, "data"=>"connection_id"=>"4b7b91001befb160d17b", "success"=>nil, "result"=>nil, "token"=>nil, "server_token"=>nil]]

client id is 4b7b91001befb160d17b
[:message, "[[\"client_connected\",\"id\":null,\"channel\":null,\"user_id\":null,\"data\":\"connection_id\":\"4b7b91001befb160d17b\",\"success\":null,\"result\":null,\"token\":null,\"server_token\":null]]"]

JSON message is
[["websocket_rails.ping", "id"=>nil, "channel"=>nil, "user_id"=>nil, "data"=>, "success"=>nil, "result"=>nil, "token"=>nil, "server_token"=>nil]]

Sending ["pong",]
[:message, "[[\"websocket_rails.ping\",\"id\":null,\"channel\":null,\"user_id\":null,\"data\":,\"success\":null,\"result\":null,\"token\":null,\"server_token\":null]]"]
[:close, 1006, ""]

websocket-rails的日志是:

I [2015-06-27 02:08:45.250] [ConnectionManager] Connection opened: #<Connection::2b3dddaf3ec4ed5e3550>
I [2015-06-27 02:08:45.251] [Dispatcher] Started Event: client_connected
I [2015-06-27 02:08:45.251] [Dispatcher] Name: client_connected
I [2015-06-27 02:08:45.251] [Dispatcher] Data: "connection_id"=>"2b3dddaf3ec4ed5e3550"
I [2015-06-27 02:08:45.251] [Dispatcher] Connection: #<Connection::2b3dddaf3ec4ed5e3550>
I [2015-06-27 02:08:45.251] [Dispatcher] Event client_connected Finished in 0.000174623 seconds
I [2015-06-27 02:09:05.252] [ConnectionManager] Connection closed: #<Connection::2b3dddaf3ec4ed5e3550>
I [2015-06-27 02:09:05.252] [Dispatcher] Started Event: client_disconnected
I [2015-06-27 02:09:05.252] [Dispatcher] Name: client_disconnected
I [2015-06-27 02:09:05.252] [Dispatcher] Connection: #<Connection::2b3dddaf3ec4ed5e3550>
I [2015-06-27 02:09:05.253] [Dispatcher] Event client_disconnected Finished in 0.000236669 seconds

可能我错过了一些非常愚蠢的东西,所以我在这里寻求您的帮助!

【问题讨论】:

【参考方案1】:

您可以使用 Iodine 作为 websocket 客户端(我是作者):

require 'iodine/http'
# prevents the Iodine's server from running
Iodine.protocol = :timer
# starts Iodine while the script is still running
Iodine.force_start!
options = 
options[:on_open] = Proc.new puts 'Connection Open'; write "Hello World!" 
options[:on_close] = Proc.new puts 'Connection Closed'
options[:on_message] = Proc.new |data| puts "I got: #data" 

# connect to an echo server for demo. Use the blocking method:
websocket = Iodine::Http::WebsocketClient.connect "wss://echo.websocket.org/", options
websocket << "sending data"
sleep 0.5
websocket.close

顺便说一句,在阅读时我注意到websocket-rails gem 并没有更新太多。见this question

作为替代方案,您可以使用 Plezi framework(我是作者)在 Rails 应用程序中运行 websockets。

在同一台服务器上同时使用这两个框架非常容易。这样您就可以在 Plezi Websocket 控制器中使用 Rails 模型的代码。

因为 Plezi 将管理 websockets 而 Rails 可能会呈现 404 Not Found 页面,所以 Plezi 的路由将优先...但只要你的路由不相互覆盖,你就是黄金。

请注意,为了让两个应用程序一起运行,Plezi 将强制您使用Iodine server 作为您的机架服务器。为避免这种情况,您可以使用 Placebo API 并在不同的进程上运行 Plezi。

您可以阅读更多框架的README file。

【讨论】:

以上是关于从 rails runner 内部触发/订阅 websocket-rails 事件的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails 中的 Runner

Rails 3 runner 没有检测到 JSON gem?

使用一些参数运行 rails runner

带有docker的Gitlab runner不会在本地缓存rails gem

text rails runnerでlib配下のスクリプト実行时に需要できない

仅限内部网络的VM上的GitLab Runner