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

Realtime connection unable to reconnect after TIMED_OUT #1088

Open
2 tasks done
farzd opened this issue Jul 8, 2024 · 4 comments
Open
2 tasks done

Realtime connection unable to reconnect after TIMED_OUT #1088

farzd opened this issue Jul 8, 2024 · 4 comments
Labels
bug Something isn't working

Comments

@farzd
Copy link

farzd commented Jul 8, 2024

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

When the realtime connection is lost on a native iOS/Android device [using Expo], attempting to auto reconnect always results in a loop. Keeps disconnecting after a reconnect.

To Reproduce

After a successful SUBSCRIBED subscription status, minimise the mobile app and lock the phone for 3 seconds.
After reverting back to the app you should get two CHANNEL_ERROR subscription statuses
[If you stay in the app, supabase manages to reconnect most of the time automatically]

But if you repeat the process before this reconnection and minimise the mobile app and lock the phone for 3 seconds. Reverting back to the app results in two more CHANNEL_ERROR subscription statuses. Followed by a CLOSED. After 10 seconds this results in a TIMED_OUT. if you start the reconnection process within this 10 seconds - the subscription fluctuates between SUBSCRIBED and CLOSED in a loop

Expected behavior

After CLOSED, the user defined reconnection strategy should result in a successful SUBSCRIBED state.
This works if i manually disconnect [the disconnect button at the top in the screenshot triggers a removeChannel call for the active subscription ]

Screenshots

[see status log in the black]
IMG_2171

System information

  • OS: iOS / Android native mobile applications [using Expo]
  • Version of supabase-js: ^2.42.5

Additional context

The basic version of my reconnection strategy, i have tested this with various methods [like reconnectingFlag] etc etc but still failing to avoid the loop described above. I've also used a flag for channel status and to only reconnect when status is not 'joined' but the TIMED_OUT forces a CLOSED after it and i'm getting strange race conditions.

IMG_2174

 const subscriptionRef = useRef(null)
 const reconnectAttemptsRef = useRef(0)

  useEffect(() => {
    if (user_id) {
      subscribeToChannel()
    }

    return () => {
      if (subscriptionRef.current) {
        supabase.removeChannel(subscriptionRef.current)
      }
    }
  }, [user_id])

  const subscribeToChannel = () => {
    subscriptionRef.current = supabase
      .channel(`XXX:${user_id}`)
      .on(
        'postgres_changes',
        {
          event: '*',
          schema: 'public',
          table: 'table',
          filter: `user_id=eq.${user_id}`,
        },
        (payload) => {
          // Reset reconnect attempts on successful message
          reconnectAttemptsRef.current = 0;
        }
      )
      .subscribe((status) =>  {
        console.log({ status });

        if (status === "SUBSCRIBED") {
          console.log("Successfully subscribed");
          reconnectAttemptsRef.current = 0;

        } else if (status === "CLOSED") {
          console.log("Subscription closed");
          reconnectWithBackoff();
        }
      })
  }

  const reconnectWithBackoff = () => {
    if (
      reconnectAttemptsRef.current < 5
    ) {
      const delay = 3000 * Math.pow(2, reconnectAttemptsRef.current)
      console.log(`Reconnecting in ${delay}ms...`)

      setTimeout(() => {
        console.log(`Reconnect attempt ${reconnectAttemptsRef.current + 1}`)
        subscribeToChannel()
        reconnectAttemptsRef.current += 1
      }, delay)
    } else {
      console.log('Max reconnection attempts reached. Please try again later.')
    }
  }
@farzd farzd added the bug Something isn't working label Jul 8, 2024
@farzd
Copy link
Author

farzd commented Jul 8, 2024

i'm resorting to this for now, not sure if its gonna have any performance implications on the server

  const subscriptionRef = useRef(null)

  AppState.addEventListener('change', (state) => {
    if (state === 'active') {
      if (!subscriptionRef.current) {
        subscribeToChannel()
      }
    } else {
      if (subscriptionRef.current) {
        supabase.removeChannel(subscriptionRef.current)
        subscriptionRef.current = null
      }
    }
  })

@flogy
Copy link

flogy commented Jul 25, 2024

@farzd I too have the issue that my customers tell me some values are not updated anymore, which for me is clearly because of broken realtime connections. When testing locally, it seem to always reconnect after the app was in background or the network connection was interrupted, thought. Were you able to fix your issue using the foreground change listener above?

@farzd
Copy link
Author

farzd commented Jul 27, 2024

@flogy i've raised a ticket and the team got back to me. [10th July]

Hi Farzad,

We've been seeing this as a common issue with mobile applications that user Expo or React Native. We're actively working on debugging what could be wrong on our side but it seems that we need to move some of the JWT refresh logic to background workers as that seems to be breaking when something is moved to be inactive.

Thank you for reporting the issue and we will inform in the issue when we have more information.

i'm finding that the reconnect on app foregrounding appears to be functioning faster / better than maintaining the same connection, mentioned above: #1088 (comment)
[of course be aware that upon initial subscription connection you get a full payload, AFAIK]
And the server load seems to be fine with this strategy

@Justinyu1618
Copy link

Hey @filipecabaco , thanks for the fix on this PR: supabase/realtime-js#121

Does this provide any benefit to running Supabase in a mobile app that gets backgrounded? If not, do you have any suggestions on how to use Supabase realtime in the mobile environment?

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants