Streaming-Client or WebRTC-SDK instance alive even after cleanup

Hi,
I have an application which integrates genesys-cloud-webrtc-sdk via CDN.
SDK CDN link : https://sdk-cdn.mypurecloud.com/webrtc-sdk/v10.0.0/genesys-cloud-webrtc-sdk.bundle.min.js
SDK Version : 10.0.0

The flow of my application :

  1. Obtain token to be used in creating genesys-cloud-webrtc-sdk instance
       const sdk = new window.GenesysCloudWebrtcSdk.GenesysCloudWebrtcSdk({
          accessToken: token,
          environment: environment,
          logLevel: "info",
          optOutOfTelemetry: true,
          useHeadsets: false,
          allowedSessionTypes: [window.GenesysCloudWebrtcSdk.SessionTypes.softphone],
        });
  1. Initialize SDK via sdk.initialize();
  2. Start a softphone session
const { id, selfUri } = await sdk.startSoftphoneSession({
          phoneNumber: dialUpNum,
        });
  1. Listen to conversationUpdate events to mark the start of the call and end of the call.
  2. Use event.current[0] from the conversationUpdate and check the mostRecentCallState to be connected which is the start of the call
  3. Use event.removed[0] from the conversationUpdate and check the mostRecentCallState to be disconnected which is the end of the call
  4. Cleanup within conversationUpdate function when call end marked as below
 const cleanup = async () => {
            if (sdk) {
              const activeConversations = sdk.sessionManager?.getAllActiveConversations() || [];
              for (const conversation of activeConversations) {
                if (conversation?.sessionId) {
                 // to terminate any session which failed and is still live or active
                  await sdk.forceTerminateSession(conversation.sessionId);
                }
              }
              await sdk.destroy();
              sdk = null;
              delete window["GenesysCloudWebrtcSdk"];
            }
        };

Problem
If after the call starts and before the call ends, if the websocket is disconnected which is handled by disconnected event on the SDK as below

        sdk.on("disconnected", async (info?: any) => {
          //sdk wont reconnect automatically, so abandon
          const errorMessage = "SDK websocket connection disconnected";
          await cleanup();
          reject(new Error(errorMessage));
        });

The cleanup method which does sdk.destroy is expected to "Ends all active sessions, disconnects the streaming-client, removes all event listeners, and cleans up media" which is helpful as the above process repeats for the next call.

However it seen that even though disconnected event is fired, the WebSocket connection is reconnected post calling and finishing up cleanup which also should disconnect the streaming-client

The reconnected WebSocket then keeps sending pings to remain alive. Now when the next call is generated by the above process, I receive -- "received a conversation event for a conversation we are not responsible for. not processing" message in the console which effectively hinders my call flow and the SDK events are not captured. I can see in the network tab that the newly created WebSocket for the new session and the reconnected WebSocket both receive jabber messages for the same conversationId

Is there a way to sort this out ?

  1. Could it be that the cleanup method is not sufficient enough to clean/remove the SDK instance ? how to check if multiple SDK instances are being created ?
  2. Or is it just because of having two streaming-clients (WebSocket) alive at the same time associated to the user ?

Any help or guidance is appreciated. Thanks in advance.

Hey,

I've taken a look at your code and both the genesys-cloud-webrtc-sdk and genesys-cloud-streaming-client and found a couple of issues on our end.

Firstly, when a streaming-client websocket is disconnected it will actually attempt to reconnect, which is why you're seeing that first websocket still. The documentation in the SDK seems to be out of date, this reconnect logic was added a couple years ago and that section of the documentation hasn't been updated since, so I'll get that updated.

Secondly, to help inform your application of the reconnect, we're going to proxy through a reconnecting value through the SDK when it emits a disconnected event. In the streaming client this looks like:

    this.emit('disconnected', { reconnecting: this.autoReconnect });

We'll just do the same thing in the SDK so you can then determine if you should tear down your SDK instance or keep it alive and wait for the reconnect. In your case, you should not tear down your SDK and instead wait for the reconnect as that is the default behavior.

Until we get the SDK updated, you'll just have to assume that a streaming-client reconnect is going to happen because thats the default behavior. Once the SDK is updated, you'll be able to more easily determine if you should wait for this reconnect or if you should just go ahead and call sdk.destroy(). Your code would look something like this:

sdk.on('disconnected', async (event, info?: any) => {
  if (event.reconnect) {
    // do not call sdk.destroy()
    return;
  }
  // Your SDK tear down logic
  await sdk.destroy();
})

Hope that helps, let me know if you have any questions. We'll work on getting those docs updated and that change into the SDK.

Thanks for the information.

I have a question though.

Why wouldn't a sdk.destroy() stop all reconnecting process related to streaming-client since it internally calls disconnect() to disconnect the streaming-client? I am asking this because I have other events on which I perform cleanup() like below and not sure if that would too spring up a streaming-client reconnect too.

sdk.on("sdkError", async (event) => {
          await cleanup();
          reject(new Error(errorMessage));
        });

sdk.on("sessionEnded", async (event, reason) => {
  if (reason.condition !== "success") {
    await cleanup();
    reject(new Error(errorMessage));
  }
});

My use case requires me to always teardown both the SDK instance as well as the streaming-connection.

PS : If I call sdk.destroy() after a successful test without getting the sdk.on("disconnected"), it does not reconnect the streaming-client.

So sdk.destroy() does call disconnect() in the streaming-client, but it doesn't stop any reconnects that are already in progress. Because the default behavior for disconnected events is to just automatically reconnect, the reconnect has already started and thats why the websocket recovers in this case despite your explicit destroy() call.

So what seems to be happening is:

  • disconnected event -> emitted from streaming-client and SDK.
  • The streaming-client immediately tries to reconnect when it gets this event.
  • Your application receives the disconnected event - you try to call sdk.destroy() -> by this point the reconnect is already in progress.
  • disconnect gets called in the streaming-client, but the reconnect is in flight and not finished. If it had yet to kick off, this would prevent it and if it had already reconnected, this would tear it down.

I'm not immediately sure what the solution is here, but I will discuss with the team how we can do this better. I don't think there should be any issue with your other cleanup calls, this is likely just an issue with disconnected events due to the default retry.

Okay. I understand.

  1. Is there a way to know if the reconnect process was successful ? Would that be sdk.on('connected', (info: { reconnect: boolean }) => { }); with reconnect true ?
  2. Would there be a way to explicitly set maybe within the SDK or otherwise to not reconnect the streaming-connection instead of waiting to reconnect ? (more desirable for my use case)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.