Spec-Zone.ru › Ruby on Rails 8.1

модуль ActionCable::Channel::Streams

Action Cable Streams

Streams позволяют каналам направлять трансляции подписчику. Трансляция, как обсуждалось в другом месте, — это очередь pub/sub, в которую помещаются данные и автоматически отправляются клиентам, подключённым в этот момент. Однако это исключительно онлайн-очередь. Если вы не подписаны на поток трансляции в тот самый момент, когда отправляется обновление, вы его не получите, даже если подключитесь после его отправки.

Чаще всего транслируемые данные отправляются напрямую подписчику на стороне клиента. Канал лишь служит связующим звеном между двумя сторонами (отправителем трансляции и подписчиком канала). Вот пример канала, который позволяет подписчикам получать все новые комментарии на заданной странице:

class CommentsChannel < ApplicationCable::Channel
  def follow(data)
    stream_from "comments_for_#{data['recording_id']}"
  end

  def unfollow
    stop_all_streams
  end
end

Согласно приведённому выше примеру, подписчики этого канала будут получать любые данные, помещённые, скажем, в трансляцию comments_for_45, сразу после их появления там.

Пример трансляции для этого канала выглядит так:

ActionCable.server.broadcast "comments_for_45", { author: 'DHH', content: 'Rails is just swell' }

Если поток связан с моделью, трансляцию можно сформировать на основе модели и канала. Следующий пример подпишет на трансляцию вида comments:Z2lkOi8vVGVzdEFwcC9Qb3N0LzE.

class CommentsChannel < ApplicationCable::Channel
  def subscribed
    post = Post.find(params[:id])
    stream_for post
  end
end

Затем можно транслировать данные в этот канал с помощью:

CommentsChannel.broadcast_to(@post, @comment)

Если вы не хотите просто передавать трансляцию подписчику без изменений, можно также передать обратный вызов, который позволит изменить отправляемые данные. В примере ниже показано, как использовать это для анализа производительности в процессе:

class ChatChannel < ApplicationCable::Channel
  def subscribed
    @room = Chat::Room[params[:room_number]]

    stream_for @room, coder: ActiveSupport::JSON do |message|
      if message['originated_at'].present?
        elapsed_time = (Time.now.to_f - message['originated_at']).round(2)

        ActiveSupport::Notifications.instrument :performance, measurement: 'Chat.message_delay', value: elapsed_time, action: :timing
        logger.info "Message took #{elapsed_time}s to arrive"
      end

      transmit message
    end
  end
end

Остановить потоковую передачу всех трансляций можно, вызвав stop_all_streams.

Общедоступные методы экземпляра

stop_all_streams () Показать исходный код
# File actioncable/lib/action_cable/channel/streams.rb, line 137
def stop_all_streams
  streams.each do |broadcasting, callback|
    pubsub.unsubscribe broadcasting, callback
    logger.info "#{self.class.name} stopped streaming from #{broadcasting}"
  end.clear
end

Отписывает все потоки, связанные с этим каналом, от очереди pub/sub.

stop_stream_for (model) Показать исходный код
# File actioncable/lib/action_cable/channel/streams.rb, line 132
def stop_stream_for(model)
  stop_stream_from(broadcasting_for(model))
end

Отписывает потоки для model.

stop_stream_from (broadcasting) Показать исходный код
# File actioncable/lib/action_cable/channel/streams.rb, line 123
def stop_stream_from(broadcasting)
  callback = streams.delete(broadcasting)
  if callback
    pubsub.unsubscribe(broadcasting, callback)
    logger.info "#{self.class.name} stopped streaming from #{broadcasting}"
  end
end

Отписывает потоки от указанной трансляции broadcasting.

stream_for (broadcastables, callback = nil, coder: nil, &block) Показать исходный код
# File actioncable/lib/action_cable/channel/streams.rb, line 118
def stream_for(broadcastables, callback = nil, coder: nil, &block)
  stream_from(broadcasting_for(broadcastables), callback || block, coder: coder)
end

Запускает потоковую передачу из очереди pub/sub для broadcastables в этом канале. При необходимости можно передать callback, который будет использоваться вместо стандартного поведения — непосредственной передачи обновлений подписчику.

Передайте coder: ActiveSupport::JSON, чтобы декодировать сообщения в формате JSON перед передачей обратному вызову. По умолчанию используется coder: nil, который не выполняет декодирование и передаёт необработанные сообщения.

stream_from (broadcasting, callback = nil, coder: nil, &block) Показать исходный код
# File actioncable/lib/action_cable/channel/streams.rb, line 90
def stream_from(broadcasting, callback = nil, coder: nil, &block)
  return if unsubscribed?

  broadcasting = String(broadcasting)

  # Don't send the confirmation until pubsub#subscribe is successful
  defer_subscription_confirmation!

  # Build a stream handler by wrapping the user-provided callback with a decoder
  # or defaulting to a JSON-decoding retransmitter.
  handler = worker_pool_stream_handler(broadcasting, callback || block, coder: coder)
  streams[broadcasting] = handler

  connection.server.event_loop.post do
    pubsub.subscribe(broadcasting, handler, lambda do
      ensure_confirmation_sent
      logger.info "#{self.class.name} is streaming from #{broadcasting}"
    end)
  end
end

Запускает потоковую передачу из указанной очереди pub/sub трансляции broadcasting. При необходимости можно передать callback, который будет использоваться вместо стандартного поведения — непосредственной передачи обновлений подписчику. Передайте coder: ActiveSupport::JSON, чтобы декодировать сообщения в формате JSON перед передачей обратному вызову. По умолчанию используется coder: nil, который не выполняет декодирование и передаёт необработанные сообщения.

stream_or_reject_for (model) Показать исходный код
# File actioncable/lib/action_cable/channel/streams.rb, line 146
def stream_or_reject_for(model)
  if model
    stream_for model
  else
    reject
  end
end

Вызывает stream_for с заданной model, если она существует, чтобы запустить потоковую передачу; в противном случае отклоняет подписку.

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API