supabase / realtime

Broadcast, Presence, and Postgres Changes via WebSockets
https://supabase.com/realtime
Apache License 2.0
6.73k stars 302 forks source link

Cannot have multiple subscriptions on same table #246

Closed leandertolksdorf closed 2 years ago

leandertolksdorf commented 2 years ago

Bug report

Describe the bug

I have two independent React components from which I create supabase realtime subscriptions like this:

useEffect(() => {
  const subscription = supabase
    .from<definitions["customer"]>("customer")
    .on("*", () => console.log("change"))
    .subscribe();
  return () => supabase.removeSubscription(subscription);
});

When having both components in one page, one of the subscriptions doesn't fire on changing a row.

When changing the "*" in both components to differ from each other, for example

Component 1: "INSERT" Component 2: "UPDATE",

logging of supabase.getSubscriptions() shows that only one of them is present in bindings.

I assume the first loaded subscription is replaced with the second loaded when calling subscribe() again, and I'm not sure if this really is a bug or intended.

To Reproduce

  1. Create two separate realtime subscriptions on the same table
  2. After creating both, log supabase.getSubscriptions(). Only one will be present.
  3. Have them both load on one page
  4. Change anything in the DB and observe which subscription reacts to the change.

Expected behavior

Both callbacks are run on DB change.

WilliamFalci commented 2 years ago

@leandertolksdorf before everything Im not a supabase mantainer or official dev... but I think maybe a lil bit more of code snapshot will help to understand where is the problem, personallly I used supabase realtime to make a multilevel customer helpdesk chat, but I did it with Vu3 + Vuex, where I have a class handle the chat and the costructor is stored into Vuex so every component can access to the proper data using the store's state.

Backing on topic the code you reported

useEffect(() => {
  const subscription = supabase
    .from<definitions["customer"]>("customer")
    .on("*", query)
    .subscribe();
  return () => supabase.removeSubscription(subscription);
});

isn't the real code you applied, so it's hard understand where is the error and give to you a possible solution

w3b6x9 commented 2 years ago

@leandertolksdorf We will consider allowing multiple subscriptions on the same table in the near future. For now, you'll just have to use a single subscription, get the changes, and then do some filtering client-side.

I'm going to close this issue b/c we intentionally enable a single subscription per table at the moment.

Marviel commented 2 years ago

@w3b6x9 Any idea where this sits on the future roadmap? It would be pretty useful from our perspective.

w3b6x9 commented 2 years ago

@w3b6x9 Any idea where this sits on the future roadmap? It would be pretty useful from our perspective.

@Marviel it's currently not on the roadmap. what are you trying to do that you can't with the existing unique subscription?

Marviel commented 2 years ago

@w3b6x9 By analogy, consider a Reddit-Like application, where most messages are public to all users.

If a user desired realtime updates on only the messages that were currently visible, it would be very excessive to subscribe to all messages on the entire platform.

Being able to subscribe to a single id using the from('foo_name:id=eq.200') pattern is a start... but if there are multiple ids on the screen, this is insufficient, so we would need multiple subscriptions.

If we are not allowed multiple subscriptions, we would need something like the in query discussed here to resolve this concern.

Marviel commented 2 years ago

UPDATE: Actually, it appears my understanding of the limitation here is inaccurate, based on this discussion post here: https://github.com/supabase/supabase/discussions/5684

It appears we can subscribe to multiple ids using separate statements like from(foo_name:id=eq.6) and from(foo_name:id=eq.7) because they are treated as separate table references.

Apologies for the misunderstanding.

w3b6x9 commented 2 years ago

@Marviel yep, you can listen to as many unique ids as you want. The limitation here is that you can't listen to foo_name:id=eq.7 twice using the same client.

Also, depending on one's use case they can also enable RLS and create the right policies so it's filtered automatically on the server so client can listen to just a schema or table and b/c of security client will only receive messages as specified by RLS policies.