Skip to content

Request for comment on API shapes #9

@fergald

Description

@fergald

We are considering 3 different APIs and would appreciate feedback. I will include some pros and cons but in order for us to correctly weight these, please comment even if it has already been called out as a pro/con and it's important to you.

This issue focuses on how to set new data on the beacon and deal with a beacon that has already sent its data.

Low-level APIs

These are 2 versions of the API in the explainer. Sync vs async is about the API shape, a sync API does not mean that operations will block, waiting for external events, rather it means that the API does not use Promises and that state cannot spontaneously change mid-task.

Sync

We have setData and isPending and if isPending returns true then the beacon has not been sent yet and setData will succeed. We could also remove isPending and have setData throw an exception but that's not fundamentally different.

Pros

  • naive code to check and set the data works

Cons

  • harder to implement

Async

We have only setData and no isPending. setData returns a Promise that will resolve if the beacon has not been sent yet and the data was successfully set. It will reject if the data could not be set.

The reason we drop isPending is because the result could be invalid by the time we try to act on it.

Pros

  • simpler to implement

Cons

  • dealing with rejected calls to setData is tricky, especially if multiple calls are in flight, full example in the explainer.

High-level API

There are two straight-forward use cases for the beacon that suggest higher level APIs. Both of these could be implemented using the lower level API above. The real question is whether these 2 high-level APIs are enough or do we need to expose the low-level API?

In both of these, there is no isPending or even a way to tell if data has been sent already.

Appending data

The beacon accumulates data and batches it up for sending. Policies like timeouts etc control how batching occurs (some data may be sent before the page is discarded). It guarantees (to the extent possible) that all data appended will eventually be sent.

The page never needs to check if the beacon has already sent some intermediate batch, it just keeps appending data.

Replacing data

The beacon's data is replaced by calls to setData. It doesn't matter whether the beacon has already sent data, it can always be replaced. Again, policies like timeouts etc control when sending occurs with a guarantee that the last set value will be definitely be sent.

Use case, e.g. reporting LCP values. The page just keeps setting the latest observed LCP, perhaps with a policy that says "don't leave data sitting around unsent for more than 5 minutes".

Discussion

An example of where these APIs might not work well is where the page would like to merge 2 metrics into 1 beacon if possible. With the low-level API, it would check if the beacon has been sent already and if not, replace the data with the combined data. This could reduce network traffic (although arguably connection reuse and header compression makes that a small benefit). It could also reduce processing cost by delivering related data already joined.

It may be that these APIs are capable of doing everything that's needed but impose costs on the backend.

It may also be that there are use-cases that simply cannot be met with these APIs.

Please let us know.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions