Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[BRUG Minsk, May 2017] Action Cable. Making Better

[BRUG Minsk, May 2017] Action Cable. Making Better

Vladimir Dementyev

May 13, 2017
Tweet

More Decks by Vladimir Dementyev

Other Decks in Programming

Transcript

  1. Action Cable in a Nutshell Server Client WebSocket Client WebSocket

    stream C Broadcaster stream B stream A stream B channel X channel Y channel Z
  2. Action Cable Channel class AnswersChannel < ApplicationCable::Channel def subscribed reject_subscription

    unless current_user.admin? end def follow(params) stream_from "questions/#{params['id']}" end end
  3. Good Parts • Easy configuration • Application logic access through

    channels • JavaScript client that just works
  4. Memory Cable 20k connections MB 0 375 750 1 125

    1 500 1 875 2 250 2 625 3 000 Go Erlang ActionCable (2x) ActionCable (16x)
  5. WebSocket Shootout Broadcast RTT 0s 1s 2s 3s 4s 5s

    6s 7s 8s 9s 10s Number of connections 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Go Erlang ActionCable Running on AWS EC2 c3.4xlarge (16 vCPU, 30 GiB RAM)
  6. Testing Cable class ServiceTest < ActionCable::TestCase def test_assert_transmited_message Service.broadcast 'messages',

    'hi!' assert_broadcast_on('messages', text: 'hi!') end def test_assert_broadcast_on_again assert_broadcast_on('messages','h!') do Service.broadcast 'messages', text: 'h!' end end end
  7. Testing Cable class ChannelTest < ActionCable::Channel::TestCase def test_subscribed_with_room_number subscribe room_number:

    1 assert subscription.confirmed? assert "chat_1", streams.last end def test_perform_speak subscribe room_number: 1 perform :speak, message: "Hello" assert_equal "Hello", transmissions.last["message"]["text"] end end
  8. Memory Cable 20k connections MB 0 500 1 000 1

    500 2 000 2 500 3 000 3 500 4 000 anycable-go erlycable ActionCable
  9. WebSocket Shootout Broadcast RTT 0s 1s 2s 3s 4s 5s

    6s 7s 8s 9s 10s Number of connections 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 ActionCable anycable-go erlycable Running on AWS EC2 c3.4xlarge (16 vCPU, 30 GiB RAM)
  10. Compatibility Feature Status Connection Identifiers + Connection Request (cookies, params)

    + Disconnect Handling + Subscribe to channels + Parameterized subscriptions + Unsubscribe from channels + Subscription Instance Variables - Performing Channel Actions + Streaming + Custom stream callbacks - Broadcasting +
  11. Action Cable Channel class ChatChannel < ApplicationCable::Channel def subscribed stream_from

    "chat_#{chat_id}" do |msg| if msg['sent_at'].present? delay = Time.now.to_f - msg['sent_at'] logger.info "Message delay #{delay}s" end transmit msg end end end
  12. WebSocket Shootout Broadcast RTT 0s 1s 2s 3s 4s 5s

    6s 7s 8s 9s 10s Number of connections 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 ActionCable Patch 1 Running on AWS EC2 c3.4xlarge (16 vCPU, 30 GiB RAM)
  13. LiteCable module Chat # ... class Channel < LiteCable::Channel::Base identifier

    :chat def subscribed stream_from "chat_#{chat_id}" end end end run Rack::Builder.new do map '/cable' do use LiteCable::Server::Middleware, connection_class: Chat::Connection run proc { |_| [200, {}, ['']] } end end
  14. • Testing Support PRs • AnyCable for Performance • LiteCable

    for non-Rails • ACLI for development/testing What We Have
  15. History Stream class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{id}",

    history: { time: 5.minutes } end end class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{chat_id}", history: { size: 100 } end end
  16. Presence class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{id}", presence:

    { user_id: user_id } end end // js client cable.subscriptions.create( { channel: 'chat', id: roomId }, { presenceUpdated: function(diff) { … } } )