Action Cable issue: messages occasionally not delivering or occasionally sent to the wrong channel

£可爱£侵袭症+ 提交于 2021-02-07 19:01:22

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!