Websocket Guest Chat member-change event when switching between chats

We are noticing duplicate member-change events in the Websocket subscription set up with the Guest Chat API, when agents are switches between chat conversations.

E.g. one agents handles two chats. Every time the agent switches to/from the "other" chat, events like the two below is sent for each chat. Is there a point to these events?

They always say state: CONNECTED, so it's not like the chat that the agent put on hold gets state: HOLD or something. That the agent is CONNECTED is already implied because it happened as the agent joined the conversation.

So, these events only seems to spam the events. Is this is bug, a side effect, or per design and if so, what is the use case?

The only things that differs in the events are the metadata.correlationId - what is that?

To recreate, I start a chat using the Guest Chat API and look at the websocket events sent out as agent switches between two chats.

Example events:

Agent putting chat on hold sends this event (state CONNECTED)

{
    "topicName": "v2.conversations.chats.6a8e057a-d340-4d9f-aabb-66ed9ffc2d8b.members",
    "version": "2",
    "eventBody": {
        "conversation": {
            "id": "6a8e057a-d340-4d9f-aabb-66ed9ffc2d8b"
        },
        "member": {
            "id": "1c5f7bbc-7d06-4b14-b0fc-3dca8b7010f9",
            "state": "CONNECTED"
        },
        "timestamp": "2020-04-20T09:36:45.355Z"
    },
    "metadata": {
        "CorrelationId": "3079a590-8f0a-47dd-ac4b-13e5fc7ade39",
        "type": "member-change"
    }
}

Agent focusing a chat sends this event (same state)

{
    "topicName": "v2.conversations.chats.6a8e057a-d340-4d9f-aabb-66ed9ffc2d8b.members",
    "version": "2",
    "eventBody": {
        "conversation": {
            "id": "6a8e057a-d340-4d9f-aabb-66ed9ffc2d8b"
        },
        "member": {
            "id": "1c5f7bbc-7d06-4b14-b0fc-3dca8b7010f9",
            "state": "CONNECTED"
        },
        "timestamp": "2020-04-20T09:36:45.355Z"
    },
    "metadata": {
        "CorrelationId": "9eafd16c-ae17-4dbf-b021-73bd84f5ea4c",
        "type": "member-change"
    }
}

There's a note about duplicate events here: https://developer.mypurecloud.com/api/webchat/guestchat.html#events

Duplicate Events
Keep in mind that all events delivered through this websocket are intended to be idempotent. In certain circumstances, some events that appear to be duplicates may arrive. The PureCloud system ensures "guaranteed at least once" event delivery. A well-formed application will track the message IDs it has processed to ensure it identifies duplicated messages and ignores them.

Noted. I'll take that answer as these events fill no purpose then and we can just throw them away.

But what are those CorrelationId ? I cannot find any documentation on it.

Hello,

From what I understand, the CorrelationId is meant to be a unique identifier for an event/notification. Each different event generated/propagated by the PureCloud org to the Guest Chat client (over the websocket) would have a different CorrelationId.
If there is a server failure or the server is not sure that the event went through (like failover in the backend), it could resend that same event with the same CorrelationId.
On client side, you would just ignore this event if you already received one (with same CorrelationId).

I think the behavior you observed/described above is a different case.
When the agent switches from one chat to another (puts focus on Chat Conversation 1 in the UI, and then switches to Chat Conversation 2 in the UI), what happens is that the PureCloud client will update the state of the agent's participant in Chat Conversation 1 (setting held = true) and will update the agent's participant in Chat Conversation 2 (setting held = false).
This means that the conversation structure (one of its attributes) is updated.

A member-change event is likely triggered in this case, but as we don't expose held/retrieved state to customers, it will come with CONNECTED state in both cases (on the Guest Chat API/websocket).

So the case you described is that your GuestChat Client 1 (for Chat Conversation 1) received a CONNECTED when this conversation was put on hold (agent puts focus on chat conversation 2 in the UI).
And then, your GuestChat Client 1 (for Chat Conversation 1) received a CONNECTED when this conversation was retrieved (agent puts focus on chat conversation 1 in the UI).
That's why in this case, even if all attributes are equivalent, you have 2 different CorrelationIDs as each of them resulted from a different change in the conversation (agent held = true, and then agent held = false).

Hope this clarifies a bit.

Regards,

Thanks for the explanation.

I guess I don't see the need to send these events if they don't add any value for the clients.

Also, the documentation says on Duplicate events: :...A well-formed application will track the message IDs".

But, metdata.correlationId is not unique. The same correlationId is emitted on completely different events within the same Websocket/subscription. I have posted an example extract below.

The eventBody.id seems unique, but it's only present on v2.conversations.chats.{convId}.messages events, not on e.g. .members events. So I guess it's actually this ID that we should filter on, and that we can only filter duplicates by ID if the events are .messages ?

correlationIds are not unique:

    {
      "topicName": "v2.conversations.chats.319cdb7a-9921-4ec8-b2ad-4cd6e8181d80.messages",
      "version": "2", // MESSAGES - member-leave - WORKFLOW (PC IVR/Architect transferred to ACD)
      "eventBody": {
        "id": "26500a23-3a37-45ac-8fb8-a20af37c3969",
        "conversation": {
          "id": "319cdb7a-9921-4ec8-b2ad-4cd6e8181d80"
        },
        "sender": {
          "id": "1dbf5e0d-148f-43ca-9380-30056d515c82"
        },
        "body": "",
        "bodyType": "member-leave",
        "timestamp": "2020-03-27T05:58:06.596Z"
      },
      "metadata": {
        "CorrelationId": "430db836-1d11-40ef-bdea-d5f8b65479f0",
        "type": "message"
      }
    },
    {
      "topicName": "v2.conversations.chats.319cdb7a-9921-4ec8-b2ad-4cd6e8181d80.messages",
      "version": "2", // MESSAGES - member-join - ACD
      "eventBody": {
        "id": "a8a94739-9ff5-4603-828c-b98c43a4e798",
        "conversation": {
          "id": "319cdb7a-9921-4ec8-b2ad-4cd6e8181d80"
        },
        "sender": {
          "id": "eb38553e-708a-4c88-8bbf-1c9bc6e6723e"
        },
        "body": "",
        "bodyType": "member-join",
        "timestamp": "2020-03-27T05:58:06.596Z"
      },
      "metadata": {
        "CorrelationId": "430db836-1d11-40ef-bdea-d5f8b65479f0",
        "type": "message"
      }
    },
    {
      "topicName": "v2.conversations.chats.319cdb7a-9921-4ec8-b2ad-4cd6e8181d80.members",
      "version": "2", // MEMBERS - member-change > DISCONNECTED - WORKFLOW
      "eventBody": {
        "conversation": {
          "id": "319cdb7a-9921-4ec8-b2ad-4cd6e8181d80"
        },
        "member": {
          "id": "1dbf5e0d-148f-43ca-9380-30056d515c82",
          "state": "DISCONNECTED"
        },
        "timestamp": "2020-03-27T05:58:06.602Z"
      },
      "metadata": {
        "CorrelationId": "430db836-1d11-40ef-bdea-d5f8b65479f0",
        "type": "member-change"
      }
    },

Yes. You are right. Missed that ones in my test, on correlationID in different places (nb: i am not from engineering so I am just running the test and checking network logs).

The eventBody.id seems indeed the proper one to use on .messages

  • for metadata.type=message with eventBody.bodyType = standard/notice/member-join/member-leave.
  • Running a test, it seems also to be unique for typing indicator (for metadata.type=typing-indicator).

So not sure about the need for .members. If the websocket is still connected and a request is sent by the Guest Chat client to be removed from the conversation, there is a member-leave received for the guest member.

Regarding member-change trigger in your test, i think that it was due to the held=true/false on Agent side (when switching focus from one chat to another).

Alright.

There seems like there is a specific design plan how to these consume these events, but the guest chat documentation doesn't touch all topics in detail.

So we are ending up doing lots of tests and trying figure out the canonical way of consuming these events in our webchat solution. As you say, both .members and .messages events seems to be viable to showcase many of the same events to the guest.

I understand.

For metadata.type=message, the eventBody.id is most probably reliable as these messages get stored (for chat transcript/...) and must have a unique id.

As you have probably understood already, they will correspond to the entities[xxx].id in the GET /api/v2/webchat/guest/conversations/{conversationId}/messages response.
Or to the messageId in the GET /api/v2/webchat/guest/conversations/{conversationId}/messages/{messageId}

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