[英]mixing redis actioncontroller::live - rails app
I am using for the first time redis
to put chat functionality in my rails app, following this 我使用的是第一次
redis
把聊天功能在我的Rails应用程序,以下这
I have in my javascript` 我的JavaScript中有`
$(document).ready ->
source = new EventSource('/messages/events')
source.addEventListener 'messages.create', (e) ->
message = $.parseJSON(e.data).message
console.log(message)
$(".chat-messages").append "#some code"
and in my message controller 在我的消息控制器中
def create
response.headers["Content-Type"] = "text/javascript"
attributes = params.require(:message).permit(:content, :sender_id, :sendee_id)
@message = Message.create(attributes)
respond_to do |format|
format.js { render 'messages/create.js.erb' }
end
$redis.publish('messages.create', @message.to_json)
end
def events
response.headers["Content-Type"] = "text/event-stream"
redis = Redis.new
redis.subscribe('messages.*') do |on|
on.message do |pattern, event, data|
response.stream.write("event: #{event}\n")
response.stream.write("data: #{data}\n\n")
end
end
rescue IOError
logger.info "Stream closed"
ensure
redis.quit
response.stream.close
end
The problem is that first, nothing is logged in my console, and second I get numbers of random ConnectionTimeoutError
errors. 问题是,首先,控制台中未记录任何内容,其次,我得到了一些随机的
ConnectionTimeoutError
错误。 Some one hava an idea what's going on 有人知道发生了什么事
Create a redis.rb
initializer file in the config/initializers
directory, globalizing an instance of redis
. 在
config/initializers
目录中创建redis.rb
初始化程序文件,以全球化redis
实例。 It's also a good idea to set up a heartbeat
thread (Anything from 5 seconds to 5 minutes is okay, depending on your requirements): 设置
heartbeat
线也是一个好主意(5秒到5分钟的时间都可以,取决于您的要求):
$redis = Redis.new
heartbeat_thread = Thread.new do
while true
$redis.publish("heartbeat","thump")
sleep 15.seconds
end
end
at_exit do
# not sure this is needed, but just in case
heartbeat_thread.kill
$redis.quit
end
You need to add two methods to your ChatController
, pub
and sub
. 您需要向
ChatController
添加pub
和sub
两个方法。 The role of pub
is to publish chat events and messages to redis
, and sub
to subscribe to these events. pub
的作用是将聊天事件和消息发布到redis
,并sub
订阅这些事件。 It should look something like this: 它看起来应该像这样:
class ChatController < ApplicationController
include ActionController::Live
skip_before_filter :verify_authenticity_token
def index
end
def pub
$redis.publish 'chat_event', params[:chat_data].to_json
render json: {}, status: 200
end
def sub
response.headers["Content-Type"] = "text/event-stream"
redis = Redis.new
redis.subscribe(['chat_event']) do |on|
on.message do |event, data|
response.stream.write "event: #{event}\ndata: #{data}\n\n"
end
end
rescue IOError
logger.info "Stream Closed"
ensure
redis.quit
response.stream.close
end
end
In your routes
, make pub a POST
and sub a GET
, and match the path to something like /chat/publish
and /chat/subscribe
. 在您的
routes
,将pub设为POST
并将sub设为GET
,然后将路径匹配到/chat/publish
和/chat/subscribe
。
Assuming your actual webpage for the chat app is at /chat
, you need to write some Javascript to actually send and receive chat messages. 假设聊天应用程序的实际网页位于
/chat
,则需要编写一些Javascript才能实际发送和接收聊天消息。
For ease of understanding, let's suppose your webpage only has a textbox and a button. 为了便于理解,我们假设您的网页只有一个文本框和一个按钮。 Hitting the button should publish the content of the textbox to the chat stream, we can do that using AJAX:
点击按钮应将文本框的内容发布到聊天流,我们可以使用AJAX做到这一点:
$('button#send').click (e) ->
e.preventDefault()
$.ajax '/chat/publish',
type: 'POST'
data: {
chat_data: {
message: $("input#message").val(),
timestamp: $.now()
}
}
error: (jqXHR, textStatus, errorThrown) ->
console.log "Failed: " + textStatus
success: (data, textStatus, jqXHR) ->
console.log "Success: " + textStatus
Now, you need to be able to subscribe and receive the chat messages as well. 现在,您还需要能够订阅和接收聊天消息。 You need to use
EventSource
for this. 您需要为此使用
EventSource
。 Using EventSource , open a channel for SSE so that you can receive events, and use that data to update the view. 使用EventSource ,为SSE打开一个通道,以便您可以接收事件,并使用该数据更新视图。 In this example, we will only log them to the javascript console.
在此示例中,我们仅将它们记录到javascript控制台。
The code should look something like this: 代码应如下所示:
$(document).ready ->
source = new EventSource('/chat/subscribe')
source.addEventListener 'chat_event', (e) ->
console.log(e.data)
In your development environment, you'll have to enable parallel requests by adding these two lines to your config/environments/development.rb
: 在开发环境中,您必须通过将这两行添加到
config/environments/development.rb
来启用并行请求:
config.preload_frameworks = true
config.allow_concurrency = true
Now fire up your browser, browse to /chat
and see the magic. 现在启动您的浏览器,浏览至
/chat
并查看魔术。 When you type a message and click the button, the message will be received by all instances of that webpage. 当您键入一条消息并单击按钮时,该网页的所有实例都会收到该消息。
Well this is how you make a basic chat application in rails
using ActionController::Live
and Redis
. 好的,这就是使用
ActionController::Live
和Redis
在rails
创建基本聊天应用程序的方式。 The final code would obviously be very different depending on your requirements but this should get you started. 最终的代码显然会根据您的要求而有很大不同,但这应该可以帮助您入门。
Some more resources you should check out: 您应该查看更多资源:
Although I've not used redis
in this capacity (a mediator for "live" data), I managed to get this functionality working with Pusher
尽管我没有以这种身份使用
redis
(“实时”数据的中介),但我设法使此功能与Pusher
一起使用
Redis 雷迪斯
I don't understand how you're keeping the connection open between your app & Redis. 我不明白您如何保持应用程序和Redis之间的连接打开。 You'll need some sort of web socket or concurrent-connection tech in place to handle the updates -- and to my knowledge, Redis does not handle this directly
您需要适当的Web套接字或并发连接技术来处理更新-据我所知,Redis不会直接处理此问题。
If you look at this example , it uses a server called Goliath to handle the asynchronous
connectivity: 如果查看此示例 ,它将使用一个名为Goliath的服务器来处理
asynchronous
连接:
When tiny-chat connects to the server it sends a GET request to /subscribe/everyone where everyone is the name of the channel and with the “Accept” header set to text/event-stream.
当mini-chat连接到服务器时,它将向/ subscribe / everyone发送GET请求,每个人都是通道的名称,并且“ Accept”标头设置为text / event-stream。 The streaming middleware (above) receives this request and subscribes to a redis Pub/Sub channel.
流中间件(上方)接收此请求并订阅redis发布/订阅通道。 Since Goliath is non-blocking multiple clients can be listening for events without tying up a Heroku dyno.
由于Goliath处于非阻塞状态,因此多个客户端可以监听事件而无需占用Heroku dyno。 The payload of a server sent event looks like this:
服务器发送事件的有效负载如下所示:
That basically uses Middleware to connect you to the redis server -- allowing you to receive updates as required 这基本上是使用中间件将您连接到Redis服务器-允许您根据需要接收更新
Code 码
Although I can't pinpoint any errors specifically, I can give you some code we're using (using Pusher ): 尽管我无法精确指出任何错误,但可以为您提供一些我们正在使用的代码(使用Pusher ):
#config/initializers/pusher.rb
Pusher.url = ENV["PUSHER_URL"]
Pusher.app_id = ENV["PUSHER_APP_ID"]
Pusher.key = ENV["PUSHER_KEY"]
Pusher.secret = ENV["PUSHER_SECRET"]
#app/controllers/messages_controller.rb
def send_message
id = params[:id]
message = Message.find(id).broadcast!
public_key = self.user.public_key
Pusher['private-user-' + public_key].trigger('message_sent', {
message: "Message Sent"
})
end
#app/views/layouts/application.html.erb
<%= javascript_include_tag "http://js.pusher.com/2.1/pusher.min.js" %>
#app/assets/javascripts/application.js
$(document).ready(function(){
#Pusher
pusher = new Pusher("************",
cluster: 'eu'
)
channel = pusher.subscribe("private-user-#{gon.user}")
channel.bind "multi_destroy", (data) ->
alert data.message
channel.bind "message_sent", (data) ->
alert data.message
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.