问题
I'm using Action Cable for a chat application with many different channels. Everything is set up with Redis and Postgresql (to save messages) on Heroku and 95% of the time works great in development and production.
Occasionally though, messages sent do not show up. The message is sent, it is saved in the database, but then it never shows up on the front end unless I refresh. Or, the message shows up in another channel for which it is not directed. Again, everything is properly saved in the Postgres database. It just gets wonky on the front end. Somewhere the ActionCable seems to get confused.
This issue happens so rarely for me, that it is very difficult to replicate to debug properly. But I have a bunch of users that are regularly reporting the issue and I'm struggling to figure out how to track it down.
Here is some of my code:
javascripts/channels/channels.js
class PodsChannel < ApplicationCable::Channel
def subscribed
stream_from "pods_channel_#{params['pod_slug']}"
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def speak(data)
#after_create_commit callback fires to create a job to broadcast message
pod_message = PodMessage.create! pod_slug: data['pod_slug'], message_body: data['message'], user_id: data['user_id'], message_type: data['msg_type']
end
end
channels/pods_channel.rb
$(document).on("ready",function(){
var pod_slug = $("#pod_slug_value").val();
// hack to prevent double posting of messages
if (!App.pods || JSON.parse(App.pods.identifier).pod_slug != pod_slug){
App.pods = App.cable.subscriptions.create(
{ channel: 'PodsChannel', pod_slug: pod_slug },
{
received: function(data) {
if ( ($(".chat-stream").length) && data.pod_slug == pod_slug ){ // hack to prevent msgs going accross pods
//#CLEAN: this is a super hackish way of preventing double messages
if(!$("#msg_" + data.msg_id).length){
$(data.message).appendTo($(".chat-stream")).find('.msg-text a').attr('target', '_blank');
$("#msg_" + data.msg_id + " .msg-text").html(Autolinker.link($("#msg_" + data.msg_id + " .msg-text").html(), { mention: "sutra" }));
$(".chat-stream").scrollTop($(".chat-stream")[0].scrollHeight);
}
}
},
speak: function(message, pod_slug, user_id, msg_type) {
return this.perform('speak',{
message: message,
pod_slug: pod_slug,
user_id: user_id,
msg_type: msg_type,
});
}
});
};
if ( $(".chat-stream").length ) {
$(".chat-stream").scrollTop($(".chat-stream")[0].scrollHeight);
};
captureMessage();
});
function captureMessage(){
$(document).on('click', "#btn-submit-msg", {}, function(){
var raw_text = $("#msg-input-text").val();
if (raw_text != ""){
submitMessage(raw_text, "pod_message");
}
});
$(document).on('keydown', '#msg-input-text', {}, function(event) {
if (event.which == 13 && !event.shiftKey && !event.ctrlKey && !event.metaKey) {
event.preventDefault();
event.stopPropagation();
if (event.target.value != "") {
submitMessage(event.target.value, "pod_message")
}
}
});
}
function submitMessage(raw_text, msg_type){
var message = raw_text;
var pod_slug = $("#pod_slug_value").val();
var user_id = $("#current_user_id_value").val();
var msg_type = msg_type;
if (App.pods.consumer.connection.disconnected == false) {
App.pods.speak(message, pod_slug, user_id, msg_type);
if (msg_type != "attachment") {
$("#msg-input-text").val("");
}
}
}
models/pod_message.rb
class PodMessage < ApplicationRecord
after_create_commit { MessageBroadcastJob.perform_now self }
end
jobs/message_broadcast_job.rb
class MessageBroadcastJob < ApplicationJob
queue_as :default
def perform(pod_message)
stream_id = "pods_channel_#{pod_message.pod_slug}"
ActionCable.server.broadcast stream_id, message: render_message(pod_message), msg_id: pod_message.id, pod_slug: pod_message.pod_slug
end
private
def render_message(pod_message)
renderer = ApplicationController.renderer.new
renderer.render(partial: 'pod_messages/pod_message', locals: { pod_message: pod_message })
end
end
来源:https://stackoverflow.com/questions/41581499/action-cable-issue-messages-occasionally-not-delivering-or-occasionally-sent-to