Skip to content

Instantly share code, notes, and snippets.

@radalin
Last active May 3, 2024 19:02
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save radalin/8a250c85a8f9bd8c727a1cf72ea3b188 to your computer and use it in GitHub Desktop.
Save radalin/8a250c85a8f9bd8c727a1cf72ea3b188 to your computer and use it in GitHub Desktop.
class ChatroomChannel < ApplicationCable::Channel
CHANNEL_NAME_TPL = "channel_%s"
# Define a periodical
periodically :check_pings, every: 10.seconds
def subscribed
_add_to_current_chats({
id: params[:chat_id],
users: [
{
connection_id: params[:connection_id],
last_updated: DateTime.now.to_i
}
]
})
end
# This is the hearbeat's check function
def check_pings
# Fetch the list of current chats with the users. We use redis, you can use db as well.
current_chats = _fetch_a_list_of_current_chats()
current_chats.each do |chat|
time_diff = DatetTime.now.to_i - chat.last_updated.to_i
if time_diff > 3600
# Clear this call from current calls, probably, it's just left there some reason
end
chat.users.each do |user|
single_user_time_diff = DateTime.now.to_i - user.last_updated
if singler_user_time_diff > 20
# Do some something as the diff is longer
ActionCable.server.broadcast CHANNEL_NAME_TPL % [chat.id], {msg: "user is dropped"}
end
if singler_user_time_diff > 10
# Do some something as the diff is longer
ActionCable.server.broadcast CHANNEL_NAME_TPL % [chat.id], {msg: "user is late"}
end
end
end
end
def ping
# It's the ping method used by the client side.
chat = _fetch_chat(params[:chat_id])
# Find the user
chat.users.each do |user|
if user.connectionId == params[:connection_id]
# Update it's last ping time
user.last_updated = DateTime.now.to_i
end
end
_save_chat(chat)
end
end
ConnectionMonitor = function(chat_id, connection_id) {
this.cableConnection = ActionCable.createConsumer("/cable");
this.subscription = null;
var self = this;
this.start = function() {
// Create a cable subscription
this.subscription = this.cableConnection.subscriptions.create({
channel: "chatroom",
chat_id: chat_id,
connection_id: connection_id
}, {
connected: function() {
// Once connection is established, start calling ping method of the channel periodically
setInterval(function() {
self.subscription.perform('ping', {
// Those values should be kept somewhere in the client side, for drops on the backend side.
chat_id: chat.id,
connection_id: chat.connection_id
});
}, 5000);
}
})
}
}
var monitor = new ConnectionMonitor("chat_id", "connection_id_of_this_user");
monitor.start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment