realtime icon indicating copy to clipboard operation
realtime copied to clipboard

Use fallback of http long-polling if firewall blocks websockets.

Open GaryAustin1 opened this issue 3 years ago β€’ 14 comments

Feature request

Currently realtime only uses websocket protocol. In some situations a user's firewall (often corporate) might block websocket or a proxy might not work.
Firebase realtime database falls back to http long-polling if websocket will not connect. At a minimum this possibility should be documented so developers can show their users a warning on possible firewall issue. Firebase long-polling: https://firebase.google.com/docs/reference/js/v8/firebase.firestore.Settings#optional-experimentalautodetectlongpolling A good link on Firebase handling of websockets/long-polling: https://github.com/firebase/firebase-js-sdk/issues/1674 Phoenix discussion on long-polling fallback: https://elixirforum.com/t/fall-back-to-longpoll-when-websocket-fails/23894

Discussion discovering a likely firewall issue: https://github.com/supabase/supabase/discussions/5856#discussioncomment-2349176

Describe the solution you'd like

Realtime should implement long-polling as a backup protocol.

Describe alternatives you've considered

Better documentation and user warning. Resort to timed polling of database which would be very inefficient.

Additional context

I don't know the extent of this issue, but at least one Supabase user/developer seems to have run into it and Firebase and Phoenix seem to at least consider it..

GaryAustin1 avatar Mar 13 '22 14:03 GaryAustin1

Thanks @GaryAustin1. I would think our client does this automatically as the Phoenix client does this.

We'll take a closer look.

chasers avatar Sep 26 '22 14:09 chasers

I don’t remember all the details on this as it was awhile ago and another user’s issue. I seem to recall that although the current Phoenix version at the time had ability to deal with it, realtime was using an older version. But I could also have that confused with Phoenix having a solution for the background timer issue and Supabase not using that.

GaryAustin1 avatar Sep 27 '22 05:09 GaryAustin1

In progress #375 ... need to update the client too, but should be solved here now.

chasers avatar Dec 14 '22 17:12 chasers

:tada: This issue has been resolved in version 1.0.0-rc.15 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket:

kiwicopple avatar Dec 21 '22 18:12 kiwicopple

:tada: This issue has been resolved in version 2.0.0-rc.1 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket:

kiwicopple avatar Dec 22 '22 00:12 kiwicopple

:tada: This issue has been resolved in version 2.0.0 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket:

kiwicopple avatar Dec 22 '22 16:12 kiwicopple

we've found some bad configurations that does not allow us to use it easily, currently checking

filipecabaco avatar Jul 05 '24 07:07 filipecabaco

Thanks @filipecabaco! Do you have a rough idea when we can expect a fix?

wiesson avatar Jul 08 '24 08:07 wiesson

already working on it, I hope to have news soonish (very optimistically during this week before my PTO πŸ˜…)

filipecabaco avatar Jul 08 '24 08:07 filipecabaco

FYI was able to do some successful testing with slight changes πŸŽ‰ I hope we're ready to share more really soon as I hope we can do this we just some changes on client libs mostly

Screenshot 2024-07-09 at 13 42 39

deno run --allow-net --allow-env --allow-read --allow-ffi --allow-sys longpoll.ts

let joinBody = {
  topic: "realtime:test",
  event: "phx_join",
  payload: {
    config: {
      broadcast: { self: true },
      presence: { key: "potato" },
      postgres_changes: [],
      private: false,
    },
  },
  ref: "1",
  join_ref: "1",
};

let apikey = "<token>";
let url = `http://127.0.0.1:54321/realtime/v1/longpoll?vsn=1.0.0&apikey=${apikey}`;
let joined = false;

async function pool() {
  console.log("Pooling...");
  let response: { status: number; token: string; messages: string[] } = await (
    await fetch(url)
  ).json();

  if (!joined) {
    url = url + `&token=${response.token}`;
    const joining = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(joinBody),
    });
    switch (joining.status) {
      case 200:
        joined = true;
        console.log("Joined");
        break;
      default:
        console.log("Error");
    }
  }

  switch (response.status) {
    case 200:
      console.log(response.messages.map(JSON.parse));
      pool();
      break;
    case 204:
      console.log("No messages");
      pool();
      break;
    case 410:
      console.log("Ready to connect");
      pool();
      break;
    default:
      console.log("Error");
  }
}

pool();

filipecabaco avatar Jul 09 '24 12:07 filipecabaco

Wonderful! Any ETA for a prod deployment? :) πŸ†

wiesson avatar Jul 11 '24 13:07 wiesson

I hope to deploy it today / tomorrow but be aware that the client lib doesn't support it, you would need to use the code above or similar.

I'll try to push forward the client lib changes and those might be merged at a later date

But if we're able to unblock you and you use this code for a while it should be ok and later you can delete it and replace with the client lib πŸ‘€

Also our aim as a first goal is to choose the transport protocol (ws or http). fallback logic will come at later date as it will require more code changes namely with message buffers to be used between both implementations πŸ€”

just want to set properly expectations πŸ˜…

filipecabaco avatar Jul 11 '24 18:07 filipecabaco

Sounds like good news! Any rough ETA when we might be able to use it in production? It's good that it might work in theory, but our enterprise customers doesn't help that.

Is there anything from our side that we could do to help? E.g. testing?

wiesson avatar Jul 22 '24 08:07 wiesson

all server changes are in production so it's really changing the realtime-js library to support different transport options (start up in ws or longpoll mode option)

Currently in PTO (this week) so after I return this feature of choosing your transportation protocol is my priority but I can't give a good ETA as that usually backfires πŸ˜…

If you want to test out with the code above you can just connect to realtime using https://<project_ref>.supabase.co/realtime/v1/longpoll?vsn=1.0.0&api_key=

sorry for the formatting, using a phone to reply it's a bit trickier

filipecabaco avatar Jul 22 '24 08:07 filipecabaco