Как заставить ActionCable отключить всех клиентов при развертывании нового кода в Heroku

У меня есть приложение, которое хранит количество всех подключений к каналу actioncable, увеличивая его на subscribed и уменьшая на unsubscribed. Однако я обнаружил проблему, из-за которой развертывание в Heroku не будет unsubscribed активных соединений, когда сервер (Puma) выйдет из строя. Таким образом, когда новая версия приложения запускается, количество подключений выше, чем должно быть.

Код для моего конкретного канала:

class PostChannel < ApplicationCable::Channel
  attr_reader :subscribers

  def subscribed
    channel_name = "TestChannel#{params[:post_id]}"
    stream_from channel_name
    user_ids = active_users channel_name
    user_ids << connection.current_user.id
    update_users channel_name, user_ids
  end

  def unsubscribed
    channel_name = "TestChannel#{params[:post_id]}"
    user_ids = active_users channel_name
    user_ids.delete_at(user_ids.index(connection.current_user.id) ||
                       user_ids.length)
    update_users channel_name, user_ids
  end

  def active_users(channel_name)
    JSON.parse(Redis.current.hget('actioncable', channel_name) || '[]')
  end

  def update_users(channel_name, user_ids)
    Redis.current.hset('actioncable', channel_name, user_ids.to_json)
    ActionCable.server.broadcast(
      channel_name,
      users: user_ids,
      action: 'UsersChanged'
    )
  end
end

Как заставить ActionCable отменить подписку на все активные подключения при развертывании к Heroku?


person JeremyKirkham    schedule 16.10.2017    source источник


Ответы (1)


Вы можете определить задачу rake, отключающую всех клиентов, а затем запустить ее с динамометрическим релизом heroku (так что она запускается каждый раз при развертывании):

procfile:

release: bundle exec rake reset_action_cable_consumers

грабли задача:

# reset_action_cable_consumers.rake

# This should work
ActionCable.server.remote_connections.disconnect

# Other solution
App.cable.subscriptions.each{|subscription| subscription.unsubscribe()}
person Graham Slick    schedule 16.10.2017
comment
Да, это было решение, о котором я думал, я попробую - person JeremyKirkham; 16.10.2017
comment
но он не будет переподключать пользователей, если они не обновят страницу? - person Nicolas Maloeuvre; 16.10.2017
comment
@NicolasMaloeuvre это не было задано в вопросе, так что нет. - person Graham Slick; 16.10.2017
comment
На самом деле @NicolasMaloeuvre клиентская библиотека, которую я использую (пакет ActionCable npm), переподключается, если она пропускает 2 пинга пульса с сервера, поэтому она должна - person JeremyKirkham; 17.10.2017