Session lifecycle

Our client SDKs expose a session object to manage the session for the active user of your application.

Whenever there is a change in user, for example when your app starts up or when a user logs in or out, you must cancel any existing session and start a new one. This is done with a single call to session.start(...).

There are a number of steps behind this call, which we collectively refer to as session priming.

Session priming

Session priming is the process of populating the session with a personalized view of all entity (Experience and Section) states from your Space.

Once primed, you can synchronously access these states indirectly through their corresponding Experience and Section instances. These instances are code generated for you by our CLI when integrating your mtribes Space.

For a clearer understanding, let's run through the SDK priming steps.

Client SDK session priming flow diagram
The flow diagram of a Client SDK priming the user's session.
  1. Developer calls session.start(...) to prime the session state for the active user.
  2. SDK makes a single request for the latest entity states under the Space targeting that user.
  3. Platform selects the correct Scenario for each Experience in the Space:
    1. Determined by executing Tribe rules for each Scenario of an Experience, top to bottom, for the active user. When there's a match, the customized state of that Scenario is selected.
    2. If no Scenario targeting finds a match, the default Scenario state is selected.
  4. Platform returns all entity states selected in a response to the SDK.
  5. Entity states are stored in latest states cache for future retrieval.
  6. If a developer has added listeners to an Experience or Section, any changes from their previous state is broadcast to these listeners.

Cache layers

In the diagram above you see three prioritized layers of entity state caches inside our SDKs.

  1. Fallback states (low)
  2. Latest states (medium)
  3. Session lock states (high)

From the outset, we've focused on safeguards to ensure the best possible user experience in any situation, which led us to this layered approach.

When accessing the state of an entity, the state is read from the session. The state returned for that entity is determined by the following rules:

  1. If the state is found in the Session lock states cache (A), return it from there directly, otherwise
  2. Check the Latest states cache (B) and if found, return it from there, otherwise
  3. Return the state from the Fallback states cache (C)

If 2 or 3 and session locking is on for the entity being queried, then populate the Session lock states cache with the returned state.

To elaborate on these rules and the details of each layer, let's explore them individually.

Fallback states

The network dilemma

Whenever an application loads an external resource, there's the risk of latency due to poor network conditions. For example; a train travelling through a tunnel, or an area with patchy cellphone coverage.

Most applications will have a long running spinner and an eventual error state. We wanted to provide a better alternative with the mtribes client SDKs, prioritizing user experience.

Retrieving personalized states

As we've learned, starting a user session will trigger a request from the SDK to get the personalized states for each Experience and Section in your Space.

This call has been heavily tuned for performance, but what happens when we hit network latency outside of our control?

Code generation

When generating your integration code, the CLI will include a snapshot of the default Scenario state of each Experience in your Space, including their ID and custom property values.

Generation will also include the current selection of Experiences a scheduler has chosen for each Section.

Default Scenarios

Default Scenarios should be seen as the generic fallback state of an Experience and their properties configured accordingly.

Default scenario example

Fallback delivery

As fallback states are bundled with your app, we can now serve them if network latency beyond an acceptable threshold occurs.

The default threshold is set to 1200 millisecond (1.2 seconds) in the SDKs, but you can customize this via the client.waitForMsec property.

For reference, we aim to respond in under 600 milliseconds, usually in the 200-400 range. While fast, we are obsessed with continually improving this.

If the threshold is exceeded, the application can continue as normal and fallbacks will be served up.

In the background, the SDK will continue to load personalized states into the latest cache and once available, will serve those up to any newly accessed Experiences and Sections.

Latest states

Latest states cache contains the most up-to-date personalized entity states for the active user.

This cache is populated when a session starts and contains a snapshot of each entity in the Space at the time the session began.

When a developer adds a change listener to an Experience or Section, this lets us know they care about updates to the state of that entity during the user's session.

The SDK will then establish a WebSocket connection with the mtribes platform and receive change notifications for that entity. For example; when a scheduler publishes changes to a Collection. The change of entity state then overwrites the previous state of this entity in the Latest states cache and the change listener is notified of the new state to read.

Session lock states

By default, any Experience or Section state surfaced to a developer from the session will be locked for the lifetime of the user's session.

For example; if the session has not completed priming and a fallback is served, it will continue to be served for the remainder of the user's session.

This is the purpose of the Session locking states cache. It locks returned entity states on the way out and then returns that state for all subsequent reads of the entity.

This is to ensure the best possible user experience, avoiding UI components swapping under them or jumping due to cumulative layout shift.

You can disable session locking for a specific entity by adding a listener to it. You'll then receive near realtime state updates over the course of the user's session for this entity.

Adding a listener when developing locally can be useful to see live updates, but take care to remove these before going to production unless you want changes to impact a user's active session.

warning

Remove any Experience or Section listeners before deploying to production, unless you intend for them to live-update during a user's session.