Skip to content

Commit cb4f5eb

Browse files
authored
Prevent broadcasting old messages when new channels are subscribed (#67)
1 parent d159d08 commit cb4f5eb

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

app/models/solid_cable/message.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Message < SolidCable::Record
77
}
88
scope :broadcastable, lambda { |channels, last_id|
99
where(channel_hash: channel_hashes_for(channels)).
10-
where(id: (last_id + 1)..).order(:id)
10+
where(id: (last_id.to_i + 1)..).order(:id)
1111
}
1212

1313
class << self

lib/action_cable/subscription_adapter/solid_cable.rb

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def shutdown
8989
end
9090

9191
def add_channel(channel, on_success)
92-
channels.add(channel)
92+
channels[channel] = last_message_id
9393
event_loop.post(&on_success) if on_success
9494
end
9595

@@ -103,21 +103,22 @@ def invoke_callback(*)
103103

104104
private
105105
attr_reader :event_loop, :thread
106-
attr_writer :last_id
107106

108-
def last_id
109-
@last_id ||= ::SolidCable::Message.maximum(:id) || 0
107+
def last_message_id
108+
::SolidCable::Message.maximum(:id) || 0
110109
end
111110

112111
def channels
113-
@channels ||= Set.new
112+
@channels ||= Concurrent::Hash.new
114113
end
115114

116115
def broadcast_messages
117-
::SolidCable::Message.broadcastable(channels, last_id).
116+
::SolidCable::Message.broadcastable(channels.keys, channels.values.min).
118117
each do |message|
119-
broadcast(message.channel, message.payload)
120-
self.last_id = message.id
118+
if channels[message.channel].present? && channels[message.channel] < message.id
119+
broadcast(message.channel, message.payload)
120+
channels[message.channel] = message.id
121+
end
121122
end
122123
end
123124

test/lib/action_cable/subscription_adapter/solid_cable_test.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,33 @@ class ActionCable::SubscriptionAdapter::SolidCableTest < ActionCable::TestCase
148148
end
149149
end
150150

151+
test "does not send old messages" do
152+
@tx_adapter.broadcast("channel", "channel1")
153+
@tx_adapter.broadcast("channel", "channel2")
154+
155+
subscribe_as_queue("channel") do |queue|
156+
assert_empty queue
157+
158+
@tx_adapter.broadcast("channel", "channel3")
159+
@tx_adapter.broadcast("channel", "channel4")
160+
@tx_adapter.broadcast("other", "other1")
161+
@tx_adapter.broadcast("other", "other2")
162+
163+
subscribe_as_queue("other") do |other_queue|
164+
assert_empty other_queue
165+
end
166+
assert_equal "channel3", queue.pop
167+
assert_equal "channel4", queue.pop
168+
end
169+
170+
@tx_adapter.broadcast("channel", "channel5")
171+
@tx_adapter.broadcast("channel", "channel6")
172+
173+
subscribe_as_queue("channel") do |queue|
174+
assert_empty queue
175+
end
176+
end
177+
151178
private
152179
def cable_config
153180
{ adapter: "solid_cable", message_retention: "1.second",

0 commit comments

Comments
 (0)