从Sidekiq广播消息只有在刷新后才显示,但在控制台中立即起作用。

4
我遵循了这篇教程创建了一个Action Cable广播,但它并没有像预期的那样正常工作。频道流和web应用程序成功订阅,但从Sidekiq后台作业广播的消息只有在刷新页面后才显示在控制台上使用相同的命令会立即更新页面
当在Chrome的开发者模式中查看帧时,无法看到来自后台作业的广播消息,但可以立即看到由控制台发送的消息。但是,我可以确认Sidekiq后台作业正在某个地方广播这些消息,因为它们在刷新后确实会显示出来;但是,我不知道它们被排队到哪里了。
是否需要进行其他配置更改以防止后台作业的消息被排队到某个地方?我的代码中是否存在任何拼写错误或错误?
Action Cable广播消息:
ActionCable.server.broadcast "worker_channel", {html:
      "<div class='alert alert-success alert-block text-center'>
        Market data retrieval complete.
    </div>"
    }

smart_worker.rb: -- 这个是在控制器的操作中作为perform_async调用的

class SmartWorker
  include Sidekiq::Worker
  include ApplicationHelper
  sidekiq_options retry: false

 def perform
   ActionCable.server.broadcast "worker_channel", {html:
      "<div class='alert alert-success alert-block text-center'>
        Market data retrieval complete.
    </div>"
    }
 end

connection.rb:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = current_user #find_verified_user ignored until method implemented correctly and does not always return unauthorized
    end

    private 

    def find_verified_user
      if current_user = User.find_by(id: cookies.signed[:user_id]) 
        current_user
      else
        reject_unauthorized_connection
      end
    end
  end
end

worker_channel:

class WorkerChannel < ApplicationCable::Channel
  def subscribed
    stream_from "worker_channel"
  end 

  def unsubscribed
  end
end

worker.js:

App.notifications = App.cable.subscriptions.create('WorkerChannel', {
  connected: function() {
    console.log('message connected');
  },
  disconnected: function() {},
  received: function(data) {
    console.log('message recieved');
    $('#notifications').html(data.html);
  }
});

cable.yml

development:
  adapter: redis
  url: redis://localhost:6379/1

test:
  adapter: async

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: smarthost_production

也将其添加到视图中,但这并没有产生影响。


你能否检查你的后台作业是否在你预期的时间有效运行? - Geoffroy
从控制台上看,它可以正常工作,但是在后台任务中,它没有发送任何消息来表明广播正在进行。 - Andrea
你能把你的代码库推送到公共的Github仓库吗?这将有助于我们解决你的问题。 - Cong Chen
我无法分享我的代码库... - Andrea
好的,是Webpacker还是Sprockets? - Cong Chen
显示剩余2条评论
2个回答

1
我不确定这是完整的解释,但这是我通过进一步测试观察到的:
多次服务器重启后,广播开始工作,并且可以按预期记录在开发记录器中。控制台消息仍然有时有时无,因此我向广播消息添加了一些额外的标识符,并确定它们在下一个页面加载完成之前被广播。这导致两件事情: 1)闪现的快速闪烁信息由广播触发(在被认为是旧页面的情况下 - 即只有在刷新后才能使用) 2)浏览器控制台行为缺乏或不一致:由于sidekiq 工作者作业很快完成,有时甚至在浏览器开始渲染新页面之前完成,我认为控制台消息被页面加载动作重置,因此在您检查日志时或即使您盯着它看一会儿也不可见。
似乎这正如预期的那样工作,只是在本地环境中工作过于迅速,使其似乎不按预期工作。

0

ActionChannel通常不会排队消息,当没有订阅者时广播的消息应该会丢失。如果通知实际上比您预期的时间晚到达,则可能会出现观察到的行为。

我建议检查以下内容:

  1. 在控制台中运行整个作业,而不仅仅是通知,并查看是否运行缓慢
  2. 检查Sidekiq队列延迟
  3. 在作业中的通知之前/之后添加日志,并检查日志以确定作业是否成功运行

我已经在logging中添加了先前和之后的记录,但从sidekiq看,它在我刷新页面之前不会记录接收到的信息(我可以在chrome控制台再次刷新之前短暂地看到记录的消息)。从rains console中,它可以立即记录。这似乎可能是一个sidekiq潜伏时间的问题,但是我已经尝试等待一段时间,行为仍然存在,只有在刷新页面后才能流/显示。 我已将其部署到heroku的staging app中,并在那里运行良好,因此该问题仅在我的本地发生。 我如何检查队列的潜伏时间? - Andrea
@Andrea,你在开发中使用哪个服务器(puma/thin/webrick..)?可能的原因是由于单线程服务器而无法接受websocket。 - Vasfed
队列延迟可以在 Sidekiq 网页中进行检查(查看队列是否正在忙于某些任务)。 - Vasfed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接