React UIKit Channel component doesn't seem to realize reconnection status

[Problem/Question]
I have a React app that uses SendBird, and I’ve been trying to implement a “connection-snooze” that would disconnect the WebSocket connection if the browser tab has been idle for a certain period of time to reduce PCC.

However, when the connection is re-established, the Channel component seems to not realize that connection has been re-established, at least not fully. If there are new messages, those are pulled in, however the message input is disabled and the “Trying to reconnect…” text persists at the bottom.

I tried a hack to recreate the component when the reconnection happens, however that causes an error:

SendbirdError: Connection is required.


// If problem, please fill out the below. If question, please delete.
[UIKit Version]
@sendbird/uikit-reactt: 3.8.2
@sendbird/chat: 4.10.3

[Reproduction Steps]
I have an idle tracker set up in the useEffect of the component that houses the chat UI implementation:

    const idleTracker = new IdleTracker({
      timeout: 1000 * 10,
      onIdleCallback: ({ idle }) => {
        if (idle) {
          if (sdkInstance.connectionState === ConnectionState.OPEN) {
            sendbirdSelectors.getDisconnect(globalStore)();
          }
        } else {
          if (sdkInstance.connectionState === ConnectionState.CLOSED) {
            sendBirdSelectors.getConnect(globalStore)(
              context.getCurrentUser()?.username as string,
              MessagingService.getService().getAccessToken(),
            );
          }
        }
      },
    });
    idleTracker.start();
    if (sdkInstance?.addConnectionHandler) {
      const connectionHandlerId = uuidv4();
      sdkInstance.addConnectionHandler(
        connectionHandlerId,
        new ConnectionHandler({
          onConnected: (userId: string) => {
            console.log('connected');
          },
          onReconnectFailed: () => {
            console.log('reconnect failed');
          },
          onDisconnected: (userId: string) => {
            console.log('disconnected');
          },
          onReconnectStarted: () => {
            console.log('start reconnect');
          },
          onReconnectSucceeded: () => {
            console.log('reconnection succeeded');
          },
        }),
      );
    }

f I add debug to getConnect via the promise it returns, the sdkInstance.connectionState does return “OPEN”, but the full SendBird system doesn’t seem to register that state, and the connection handler does provide the “disconnected” and “connected” events. The user returned by re-establishing the connection is also the right one.

[Frequency]
Always

[Current impact]
Due to the use case, there’s a high likelyhood of “idle” messaging instances running around and that might lead to an inflated PCC even though users aren’t actively using it. Not being able to curb this could balloon our bill with zero value added to users.

Hi @trinta,

Welcome to the Sendbird Community. I’m not sure if you’re aware of this but the Sendbird Chat SDK has this functionality built in. After 30 seconds of being in the background, the JS SDK will automatically disconnect the websocket until the tab/window is refocused.

Have you tried allowing the SDK to handle this natively? Outside of that, if you could provide us with a reproducible sample on something like stackblitz or codesandbox that would be great.

I … was not aware of this :smiley:

I looked for this in the documentation and did not find it, so either I just glanced over it (high likelyhood) or then it’s not there.

Appreciate the response, this makes my life much easier.

Hi @Tyler . How reliable is this? I am are trying to implement @trinta did after I came here and saw that it’s already built in. but it seems we still have a high PCC vs the number of users.

Hello @Gerald,

In terms of reliability, it’s as reliable as the browser environments ability to emit the necessary events. You can easily test this in a small sample application. Simply connect to a websocket and background the tab or window and wait 30+ seconds. You’ll notice in the network tab that the websocket gets disconnected.

Also, it’s important to note that the number of PCC can exceed the number of users depending on the implementation. Since PCC is tracked by the websocket and is not unique to the user.

@Tyler
Thanks for this information.
I understand I am late to the party here but my team came across this beautiful response while experiencing similar issue.
While trying to further understand your response, we do have the following questions

  • It seems to me that while the SB SDK helps manage the Focused & Unfocused browser/tab to help prevent unnecessarily high PCC, there could likely be a Race Condition between when a browser/tab becomes Unfocused (connection to be disconnected) vs when another browser/tab becomes Focused (new connection opens). Reason being, once a new connection opens, it counts against the PCC as a new connection and if at the moment of that connection being opened, the unfocused browser/tab hasn’t been disconnected yet for whatever reasons, the PCC is incremented which unfortunately does defeats the potential purpose of preventing an unnecessarily high PCC that adds no value to the business but potentially inflates the bill. Will appreciate it if you have some insight into this scenario above.
  • How does SB help prevent a bad actor from maliciously attacking a business using SB by opening multiple connections on multiple focused browsers/tabs with an intent to inflate the PCC and deny service to the business?
  • Is there a way SB can limit concurrent connections per user (similar to what Netflix does) or a way we could use your SDK to programmatically achieve this on the application level as a safety measure to prevent intentional & unintentional abuse/attack?
  • Is there a way to programmatically place a hard-cap on the MAU & PCC on an application within an org account (ie, if i have a staging app & production app, but I want to place a hard-cap on the staging app so as to limit the usage staging app since all apps in an account share the same quotas)
  • If non of the above exists, and we just have to solely rely on the unfocused & focused browser/tab checks with potential race condition existing, then I think this is in favor of Sendbird monetarily and also not wise to put your clients in potential situations where their bills might get unexpected blown out due to either ignorance or bad actors. Some people might see this as a loophole to generate more charges from your clients (disclaimer: this is a speculation due to insufficient information that I am hoping to receive and not with bad intent… PS. I love what SB has done but I am just worried about my bills as a startup)