ActionCable Timeout - "Idle Connection" on Heroku
Asked Answered
O

3

15

We have been using ActionCable on Heroku for some time, and overall it works well. However, we see the H15 Idle Connection error many times per day. They always have path=/cable and a long service time, so the connection was definitely live and healthy for a while.

Dec 2016 08:32:22.057 heroku router - - at=error code=H15 desc="Idle connection" 
method=GET path="/cable" host=<our host> dyno=web.2 connect=1ms service=928755ms status=503

I believe our setup is very standard, and closely follows the Rails docs for ActionCable:

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

    def connect
      self.current_user = find_verified_user
    end

    protected

    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

We have three simple channels like this:

class ActivitiesChannel < ApplicationCable::Channel  

  def subscribed
    stream_from "activities_#{current_user.id}" if current_user
  end
end

Edit to Add - Javascript code:

app/assets/javascripts/channels/setup.js:

//= require cable

this.App || (this.App = {});
App.cable = ActionCable.createConsumer(); 

app/assets/javascripts/channels/notifications.js:

App.notifications = App.cable.subscriptions.create('NotificationsChannel', {  
  received: function(data) {
      return this.showMessage(data);
  },
  showMessage: function(data) {
      showNotice(data.message);
  }
});

I'm fairly new with ActionCable and WebSockets, so I'm not sure how to troubleshoot this one. We are running Rails 5.0.0.1 with Ruby 2.3.1

Any help, context, or troubleshooting tips would be much appreciated!

Overcash answered 4/12, 2016 at 16:36 Comment(9)
I have a similar AC setup, but I donøt get the H15 errors. Can you show the javascript that initializes the cable connection?Fbi
@EmilKampp I just edited to add some of our javascript code. Thanks in advance!Overcash
what type of information are you sending across the WS connection, and how often? According to the heroku documentation a H15 occurs when a request isn't completed within 55 seconds.Fbi
@EmilKampp sorry for the delay - we send very simple text messages about real-time events. Those notifications are shown in a small status bubble on the page. We don't send them with any specific time interval; they're sent based on user actions (either their or actions, or users in their domain).Overcash
@JackCollins I'm having this same issue, did you find any resolution?Placket
@Placket unfortunately I still have not found a solution to thisOvercash
@JackCollins did you ever solve this. i have a similar problem...Tutt
@SurgePedroza nope, still haven't solved this one unfortunatelyOvercash
I just got this issue. All errors came from the same user. Otherwise, AC works fine. 🤔Misprize
L
4

EDIT: I just realized that it is an old question. Not sure, why this popped up on my feed. Anyway, it might help someone in the future.

I believe this is happening when someone keeps the page open without any activity on the channel and when the connection stays open but idle for 55 seconds, Heroku closes the connection with the error Idle connection. You have to keep the connection alive, by implementing some sort of ping system which periodically sends a message to the server and the server simply sends an ok in response. A simple example is:

app/assets/javascripts/channels/notifications.js:

App.notifications = App.cable.subscriptions.create('NotificationsChannel', {  
  received: function(data) {
    // ignore the data when the type is 'pong' as it is just server's response to our 'ping'
    if(data.type !== 'pong'){
      return this.showMessage(data);
    }
  },
  showMessage: function(data) {
    showNotice(data.message);
  },
  ping: function() {
    return this.perform('ping', {
      message: {"event": "ping"}
    });
  }
});
document.addEventListener("DOMContentLoaded", function(event) {
  // this will send a ping event every 30 seconds
  setInterval(function(){
    App.notifications.ping()
  }, 30000);
});

On the server-side, you need to send a response message e.g 'pong' to the 'ping' event. You can send that response to the same user, or broadcast to all users, depending on your channels setup and requirement.

class NotificationsChannel < ApplicationCable::Channel  

  def subscribed
    stream_from "notifications_#{current_user.id}" if current_user
  end

  # data is not required, you can choose to ignore it or not send it at all from the client-side.
  def ping(data)
    NotificationsChannel.broadcast_to("notifications_#{current_user.id}", { message: 'pong' })
  end
end

This should keep the connection alive even if the user is idle.

I have not worked with ActionCable since it's first release. Let me know if something does not work or any syntax error, I will try to fix.

Lightsome answered 4/6, 2020 at 20:39 Comment(0)
P
0

Which plan of heroku do you use? If free - don't forget that it sleeps after 30 minutes of inactivity, what might cause some H15 errors (idle connection...)

Precatory answered 16/7, 2018 at 14:16 Comment(1)
Please check plan specification and lest us know if you've found a solutionPrecatory
H
0

This probably happens because either

  1. HTTP connection isn't ended "normally" since the server returns the 101 response (Switching Protocols - to establish the websocket connection) - or
  2. at some point the underlying TCP connection breaks down (user moves to new wifi, closes laptop etc)

Being pragmatic - the resulting websocket seems to be functioning correctly on the underlying TCP connection. Any issues with the websocket connection trigger the retry logic in the browser which cleans things up from the user's perspective - so the app is functioning normally for my users despite this log message.

For my app I felt that it was safe to just ignore the H15 error code from Heroku but that may not be safe for you if you have other situations where HTTP requests could likely become hung up.

Check out the Heroku documentation for reference:

https://devcenter.heroku.com/articles/error-codes#h15-idle-connection

H15 - Idle connection

The dyno did not send a full response and was terminated due to 55 seconds of inactivity. For example, the response indicated a Content-Length of 50 bytes which were not sent in time.

2010-10-06T21:51:37-07:00 heroku[router]: at=error code=H15 desc="Idle connection" method=GET path="/" host=myapp.herokuapp.com fwd=17.17.17.17 dyno=web.1 connect=1ms service=55449ms status=503 bytes=18

Hyperaemia answered 29/10, 2018 at 18:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.