Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use separate ActionCable server to prevent disconnects #69

Merged
merged 1 commit into from
Dec 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 47 additions & 54 deletions app/assets/javascripts/hotwire-livereload.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,18 +389,18 @@
this.subscriptions = subscriptions;
this.pendingSubscriptions = [];
}
guarantee(subscription2) {
if (this.pendingSubscriptions.indexOf(subscription2) == -1) {
logger.log(`SubscriptionGuarantor guaranteeing ${subscription2.identifier}`);
this.pendingSubscriptions.push(subscription2);
guarantee(subscription) {
if (this.pendingSubscriptions.indexOf(subscription) == -1) {
logger.log(`SubscriptionGuarantor guaranteeing ${subscription.identifier}`);
this.pendingSubscriptions.push(subscription);
} else {
logger.log(`SubscriptionGuarantor already guaranteeing ${subscription2.identifier}`);
logger.log(`SubscriptionGuarantor already guaranteeing ${subscription.identifier}`);
}
this.startGuaranteeing();
}
forget(subscription2) {
logger.log(`SubscriptionGuarantor forgetting ${subscription2.identifier}`);
this.pendingSubscriptions = this.pendingSubscriptions.filter((s) => s !== subscription2);
forget(subscription) {
logger.log(`SubscriptionGuarantor forgetting ${subscription.identifier}`);
this.pendingSubscriptions = this.pendingSubscriptions.filter((s) => s !== subscription);
}
startGuaranteeing() {
this.stopGuaranteeing();
Expand All @@ -412,9 +412,9 @@
retrySubscribing() {
this.retryTimeout = setTimeout(() => {
if (this.subscriptions && typeof this.subscriptions.subscribe === "function") {
this.pendingSubscriptions.map((subscription2) => {
logger.log(`SubscriptionGuarantor resubscribing ${subscription2.identifier}`);
this.subscriptions.subscribe(subscription2);
this.pendingSubscriptions.map((subscription) => {
logger.log(`SubscriptionGuarantor resubscribing ${subscription.identifier}`);
this.subscriptions.subscribe(subscription);
});
}
}, 500);
Expand All @@ -431,64 +431,64 @@
const params = typeof channel === "object" ? channel : {
channel
};
const subscription2 = new Subscription(this.consumer, params, mixin);
return this.add(subscription2);
const subscription = new Subscription(this.consumer, params, mixin);
return this.add(subscription);
}
add(subscription2) {
this.subscriptions.push(subscription2);
add(subscription) {
this.subscriptions.push(subscription);
this.consumer.ensureActiveConnection();
this.notify(subscription2, "initialized");
this.subscribe(subscription2);
return subscription2;
}
remove(subscription2) {
this.forget(subscription2);
if (!this.findAll(subscription2.identifier).length) {
this.sendCommand(subscription2, "unsubscribe");
this.notify(subscription, "initialized");
this.subscribe(subscription);
return subscription;
}
remove(subscription) {
this.forget(subscription);
if (!this.findAll(subscription.identifier).length) {
this.sendCommand(subscription, "unsubscribe");
}
return subscription2;
return subscription;
}
reject(identifier) {
return this.findAll(identifier).map((subscription2) => {
this.forget(subscription2);
this.notify(subscription2, "rejected");
return subscription2;
return this.findAll(identifier).map((subscription) => {
this.forget(subscription);
this.notify(subscription, "rejected");
return subscription;
});
}
forget(subscription2) {
this.guarantor.forget(subscription2);
this.subscriptions = this.subscriptions.filter((s) => s !== subscription2);
return subscription2;
forget(subscription) {
this.guarantor.forget(subscription);
this.subscriptions = this.subscriptions.filter((s) => s !== subscription);
return subscription;
}
findAll(identifier) {
return this.subscriptions.filter((s) => s.identifier === identifier);
}
reload() {
return this.subscriptions.map((subscription2) => this.subscribe(subscription2));
return this.subscriptions.map((subscription) => this.subscribe(subscription));
}
notifyAll(callbackName, ...args) {
return this.subscriptions.map((subscription2) => this.notify(subscription2, callbackName, ...args));
return this.subscriptions.map((subscription) => this.notify(subscription, callbackName, ...args));
}
notify(subscription2, callbackName, ...args) {
notify(subscription, callbackName, ...args) {
let subscriptions;
if (typeof subscription2 === "string") {
subscriptions = this.findAll(subscription2);
if (typeof subscription === "string") {
subscriptions = this.findAll(subscription);
} else {
subscriptions = [subscription2];
subscriptions = [subscription];
}
return subscriptions.map((subscription3) => typeof subscription3[callbackName] === "function" ? subscription3[callbackName](...args) : void 0);
return subscriptions.map((subscription2) => typeof subscription2[callbackName] === "function" ? subscription2[callbackName](...args) : void 0);
}
subscribe(subscription2) {
if (this.sendCommand(subscription2, "subscribe")) {
this.guarantor.guarantee(subscription2);
subscribe(subscription) {
if (this.sendCommand(subscription, "subscribe")) {
this.guarantor.guarantee(subscription);
}
}
confirmSubscription(identifier) {
logger.log(`Subscription confirmed ${identifier}`);
this.findAll(identifier).map((subscription2) => this.guarantor.forget(subscription2));
this.findAll(identifier).map((subscription) => this.guarantor.forget(subscription));
}
sendCommand(subscription2, command) {
const { identifier } = subscription2;
sendCommand(subscription, command) {
const { identifier } = subscription;
return this.consumer.send({
command,
identifier
Expand Down Expand Up @@ -587,9 +587,8 @@
}, 300);

// app/javascript/hotwire-livereload.js
var consumer = createConsumer();
var subscription = null;
var createSubscription = () => consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
var consumer = createConsumer("/hotwire-livereload");
consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
received: hotwire_livereload_received_default,
connected() {
console.log("[Hotwire::Livereload] Websocket connected");
Expand All @@ -598,14 +597,8 @@
console.log("[Hotwire::Livereload] Websocket disconnected");
}
});
subscription = createSubscription();
document.addEventListener("turbo:load", () => {
hotwire_livereload_scroll_position_default.restore();
hotwire_livereload_scroll_position_default.remove();
if (subscription) {
consumer.subscriptions.remove(subscription);
subscription = null;
}
subscription = createSubscription();
});
})();
15 changes: 2 additions & 13 deletions app/javascript/hotwire-livereload.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import { createConsumer } from "@rails/actioncable"
import received from "./lib/hotwire-livereload-received"
import scrollPosition from "./lib/hotwire-livereload-scroll-position"

const consumer = createConsumer()
let subscription = null

const createSubscription = () => consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
const consumer = createConsumer("/hotwire-livereload")
consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
received,

connected() {
Expand All @@ -17,16 +15,7 @@ const createSubscription = () => consumer.subscriptions.create("Hotwire::Liverel
},
})

subscription = createSubscription()

document.addEventListener("turbo:load", () => {
scrollPosition.restore()
scrollPosition.remove()

if (subscription) {
consumer.subscriptions.remove(subscription)
subscription = null
}
subscription = createSubscription()
})

2 changes: 2 additions & 0 deletions lib/hotwire/livereload.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "action_cable/server/base"
require "hotwire/livereload/cable_server"
require "hotwire/livereload/engine"

module Hotwire
Expand Down
11 changes: 11 additions & 0 deletions lib/hotwire/livereload/cable_server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Hotwire
module Livereload
class CableServer < ActionCable::Server::Base
def initialize
config = ::ActionCable::Server::Base.config.dup
config.connection_class = -> { ::ActionCable::Connection::Base }
super(config: config)
end
end
end
end
14 changes: 13 additions & 1 deletion lib/hotwire/livereload/engine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ class Engine < ::Rails::Engine
config.hotwire_livereload.listen_options ||= {}
config.hotwire_livereload.debounce_delay_ms = 0

initializer "hotwire_livereload.routes" do
config.after_initialize do |app|
app.routes.prepend do
mount Hotwire::Livereload.cable_server => "/hotwire-livereload", :internal => true, :anchor => true
end
end
end

initializer "hotwire_livereload.assets" do
if Rails.application.config.respond_to?(:assets)
Rails.application.config.assets.precompile += %w[hotwire-livereload.js hotwire-livereload-turbo-stream.js]
Expand Down Expand Up @@ -109,8 +117,12 @@ def self.turbo_stream(locals)
)
end

def self.cable_server
@cable_server ||= Hotwire::Livereload::CableServer.new
end

def self.action_cable(opts)
ActionCable.server.broadcast("hotwire-reload", opts)
cable_server.broadcast("hotwire-reload", opts)
end

def self.server_process?
Expand Down
Loading