Skip to content

Latest commit

 

History

History
127 lines (98 loc) · 6.86 KB

File metadata and controls

127 lines (98 loc) · 6.86 KB

How are activities grouped?

Before sorting, activities are grouped as a unit:

  • Activities within the same part grouping are inserted next to each other
    • Order is based on the position property
    • Logical timestamp of the part grouping is the "maximum logical timestamp" of all parts
    • Parts can contain livestream session or ungrouped activities
  • Activities within the same livestream session will be inserted next to each other
    • Order is based on the streamSequence property
    • Logical timestamp of the livestream session is the logical timestamp of the finalizing activity (if any), or the logical timestamp of the first activity
      • In other words, livestream will be reordered when they are inserted for the first time, or when they are finalized
      • Interim updates will not reorder the livestream to avoid too much flickering
  • All other activities are not grouped, they are individual units

How are activities sorted?

Short answer: activities are sorted by logical timestamp when inserted.

Long answer:

  • For grouped activities (such as part groupings or livestream sessions), all activities within the group are treated as a unit
  • For ungrouped activities, each activity is a unit on its own

Units are sorted using their logical timestamp on insertion. If the unit is already in the chat history, they will be removed before being re-inserted.

What is logical timestamp?

By logical timestamp, in JavaScript:

logicalTimestamp = activity.channelData['webchat:sequence-id'] ?? +new Date(activity.timestamp) || +new Date(activity.localTimestamp);
  1. activity.channelData['webchat:sequence-id']: number
    • This field represents the order of the activity in the chat history and can be a sparse number;
    • This field is OPTIONAL, but RECOMMENDED;
    • This field MUST be an integer number;
    • This field MUST be a unique number assigned by the chat service;
    • This field SHOULD be consistent across all members of the conversation.
  2. Otherwise, activity.timestamp: string
    • This field represents the server timestamp of the activity;
    • This field is REQUIRED;
    • This field MUST be an ISO date-time string, for example, 2000-01-23T12:34:56.000Z;
    • This field MUST be assigned by the chat service, a.k.a. server timestamp;
    • This field SHOULD have resolution up to 1 millisecond;
    • This field MUST be the same across all members of the conversation.
  3. Otherwise, activity.localTimestamp: string
    • This field represents the local timestamp of an outgoing activity;
    • This field is REQUIRED for all outgoing activities;
    • This field MUST be an ISO date-time string, for example, 2000-01-23T12:34:56.000Z;
    • This field MUST be assigned by the sender, a.k.a. Web Chat;
    • This field SHOULD have resolution up to 1 millisecond;
    • This field MUST be the same across all members of the conversation.

Archived documentation

The following documentation is archived.

How activities are being sorted?

Web Chat sort activities based on a few sort keys stamped by the chat service, with the following fallback order:

  1. activity.channelData['webchat:sequence-id']: number
    • This field represents the order of the activity in the chat history and can be a sparse number;
    • This field is OPTIONAL, but RECOMMENDED;
    • This field MUST be an integer number;
    • This field MUST be an unique number assigned by the chat service;
    • This field SHOULD be consistent across all members of the conversation.
  2. Otherwise, activity.timestamp: string
    • This field represents the server timestamp of the activity.
    • This field is REQUIRED;
    • This field MUST be an ISO date time string, for example, 2000-01-23T12:34:56.000Z;
    • This field MUST be assigned by the chat service, a.k.a. server timestamp;
    • This field SHOULD have resolution up to 1 millisecond;
    • This field MUST be the same across all members of the conversation.

Whenever an activity is updated, Web Chat will remove the existing activity from the chat history, then insert the updated version based on the new sort keys from the updated activity.

When an activity transit from "sending" state to "sent" state, it will trigger an update. Thus, it is possible and expected that, an activity could initially appear at a certain position. When it is updated, it could move to a new position to make it consistent with other members of the conversation.

How about outgoing activities?

Since both all forementioned sort keys are assigned by the server, when the user is sending out a message, both sort keys are not available for sorting until Web Chat receive a server copy of the activities.

Web Chat will use the following algorithm to determine the temporal value of these activity-in-transit. This algorithm is applied when Web Chat is posting an activity to the chat service.

  • activity.channelData['webchat:sequence-id']: number
    1. Find the largest sequence ID in the current chat history;
    2. Increment it by 0.001;
    3. Assign the value to the activity-in-transit.
  • activity.timestamp: string
    • This field MUST be undefined.
  • activity.localTimestamp: string
    • This field is based on local clock;
    • This field MUST be an ISO date time string;
    • This field is used to determine if the chat service timed out while posting the activity.

Note: Web Chat assumes the chat service should not backlog more than 1,000 activities at a time.

After the activity-in-transit arrives at the chat service, the chat service MUST update the sort keys and send the updated activity back to Web Chat.

Assumptions of sequence ID and timestamp

Combining the algorithms above, Web Chat has the following assumptions

  • For all activities
    • activity.channelData['webchat:sequence-id'] SHOULD be set
      • If unset, Web Chat will fill this value using epoch of activity.timestamp
  • For activities from self
    • For activity-in-transit
      • activity.localTimestamp MUST be set
      • activity.timestamp MUST be undefined or unset
    • For activity that has a server copy, a.k.a. successfully sent
      • activity.localTimestamp is optional
      • activity.timestamp MUST be set
  • For activities from others
    • activity.localTimestamp is optional
    • activity.timestamp MUST be set

Related read