Closed Dandush03 closed 3 weeks ago
Never used this feature, but agree we should have parity on the return value any way.
Never used this feature, but agree we should have parity on the return value any way.
Hmm not sure this is the case across the board, @dhh. This is indeed how the redis adapter works but the postgres adapter returns this:
And the async adapter will return nil or an an array of subscribers.
I think we will need to setup another table to be able to persist subscribers...but let me think on it for a bit to see if i can come up with anything better.
Oh. Def not worth another table.
Yea while working on the implementation, i realized we will only be able to return the number of subscribers listening at the time of broadcast. Whether or not those subscribers are still subscribed when the message is picked up in the polling can't be determined at the time of broadcast. So we could end up returning incorrect numbers.
And since the broadcast method has no strict contract across all adapters on the return value, I think im going to close this out as not planned.
@dhh let me know if you disagree and we can reopen!
@npezza93 What if we add a broadcasted column to the relevant records? This could be a boolean field indicating whether the message has been broadcast.
There’s also another issue that could potentially be addressed with this approach. It seems related to how the ActionCable::Listener
memoizes the last_id
variable across requests. Because the same last_id value is being reused, the listener can't accurately determine which records have already been streamed, leading to potential duplicate broadcasts in a loop.
By introducing a broadcasted flag, we could update the status of each record during or after the broadcast to prevent duplication. This would ensure that only unprocessed records are sent in subsequent loops, improving broadcast reliability. I believe this approach offers a lightweight solution without the need for additional tables while also addressing issues with memoization during broadcasting.
Let me know if this aligns with your thoughts or if further clarification is needed!. I will attach a video of the repeatedly cast broadcast message when refreshing the page:
https://github.com/user-attachments/assets/7bc05fc7-cb7c-47d8-b732-4bce9b3ff5a4
Notice how the adapter does not know how to handle already broadcasted messages, when the rails env, is set with multithreading, depending on which thread it enter it has a diferent last_id
, but does not know how to skip or handle already broadcasted messages
What if we add a broadcasted column to the relevant records? This could be a boolean field indicating whether the message has been broadcast
This wont work, because with polling, one listener may have broadcast the message but another may not have.
Let me know if this aligns with your thoughts or if further clarification is needed!. I will attach a video of the repeatedly cast broadcast message when refreshing the page:
I would need to see some code around how this example works(specifically around how messages are broadcast). When you reload the page, you get a new cable connection and a new listener with grabs the latest message id so only new stuff would be broadcast out. If you could also show the network tab for the cable connection that shows the messages that are being broadcast to the browser, that would also be helpful.
So, I refreshed 4 times, and got 4 diferent connections, which is expected.
The first one, did broadcast old messages (unexpeted behavior)
The second and third, did not (expected behavior)
The fourth, broadcasted all messages again (unexpected behavior)
This wont work, because with polling, one listener may have broadcast the message but another may not have
In my opinion, the focus shouldn’t be on how many subscribers received the broadcast at any given moment. Instead, the goal should be to mark a message as broadcasted once it has been processed, rather than checking on each request whether it was sent.
By marking the record as broadcasted, we avoid unnecessary re-broadcasts in subsequent polling cycles. This approach simplifies the logic and ensures that messages are only broadcast once, regardless of how many listeners are connected at that exact time. The emphasis shifts from tracking every individual subscriber to maintaining message integrity by preventing duplicate broadcasts.
This way, even if some listeners miss the message due to polling timing, we maintain consistent behavior without overcomplicating the process.
regarding, code, there we are calling it as usual,
::Broadcastable::Toast.broadcast_toast(
resource: current_user,
type: :error,
title: I18n.t('.feedbacks.toast.error.title'),
content: I18n.t('.feedbacks.toast.error.content'),
date: Time.zone.now
)
And this is done in a SolidQueue::Job
😅 but it's been queue only once.
Would you be able to create a minimal rails app that reproduces this?
Would you be able to create a minimal rails app that reproduces this?
sure, I'll do it later this week
Thanks!
While using SolidCable to broadcast messages (e.g., via
broadcast_append_to
), the current return value is anActiveRecord::Result
. Although this seems to contain some metadata, it doesn’t provide direct feedback about how many subscribers/users actually received the broadcast.This lack of visibility makes it difficult to track the success of the broadcast and ensure that messages are reaching their intended audience.
Expected Behavior:
In ActionCable (Rails' default adapter for real-time features), methods such as
broadcast_append_to
,broadcast_replace_to
, etc., return the number of subscribers who successfully received the message. This allows developers to track how many users were targeted by the broadcast and confirm that it was successful.For example, in ActionCable:
This number directly reflects the total number of clients (subscribers) that received the message. Having this information is very useful when tracking message delivery, especially in applications relying on reliable real-time communication.
Current Behavior in SolidCable:
In SolidCable, the broadcast_append_to method returns an
ActiveRecord::Result
instead of aninteger
reflecting the number of recipients. While this may contain metadata about the operation, it doesn’t provide explicit feedback on how many users/subscribers actually received the broadcast.This creates a gap in visibility, as we have no easy way of confirming whether the stream was successfully delivered to all intended users or how many users it reached.
Suggested Solution:
Enhance the broadcast methods (like
broadcast_append_to
,broadcast_replace_to
, etc.) to return the number of users/subscribers who received the broadcast, similar to the behavior of ActionCable.Optional: Provide callback hooks or logging mechanisms to confirm the success of broadcasts and report the number of recipients. This could be useful for further debugging or monitoring purposes.
Why This is Important:
Having visibility into how many users receive a broadcast is critical for applications that rely on real-time communication. Without it, it is difficult to confirm that broadcasts are reaching the right audience or to debug situations where users are not receiving updates as expected.
This would bring SolidCable in line with the behavior provided by ActionCable, making it easier for developers to manage and monitor real-time message delivery.
Example of Desired Behavior:
Thank you for considering this request. I believe this feature will significantly improve the usability and visibility of SolidCable's real-time messaging capabilities.