Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automation section and WebDriver support #265

Closed
wants to merge 47 commits into from
Closed

Conversation

kenchris
Copy link
Contributor

@kenchris kenchris commented Apr 18, 2024

index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Show resolved Hide resolved
Copy link
Member

@rakuco rakuco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for taking so long to review this pull request. Supporting workers (shared workers in particular) presents additional challenges. I was also trying to take the DevTools use case into consideration; even though it's orthogonal to the spec, having the WebDriver and DevTools models be similar helps us enormously.

What we've done in Generic Sensors, Device Orientation and Device Posture is plug any overridden data into a top-level navigable, so that essentially all frames in a tab use the same override, which also persists across navigations (since it's basically tied to the tab, not the main frame). This works great for features exposed to Window, and possibly for dedicated workers too, but shared workers are tied to an origin, not a tab, and can even outlive it.

Option 1: tracking origins

One approach would be tying the pressure override information to an origin rather than a top-level navigable like the Permissions API does. Since we need more endpoints than the Permissions API, perhaps we could draw some inspiration from WebAuthn and keep a mapping of source type to a list of domains that could be referred to by an id. The pseudocode would look like this in JS:

const id = await add_override("cpu", ["kde.org", "www.foo.bar:8443"]);
await set_pressure(id, { state: "critical" });
await remove_override(id);

This works great for WebDriver and web tests but not so much for DevTools, where the effects are only supposed to last while the UI is open and only affect the current tab. We'd probably need separate CDP commands for this use case and error out when both modes are being used at the same time, and optionally just not support shared workers in this case at all.

Option 2: storing the data in the top-level traversable

The usual approach. Works great with DevTools and WebDriver, except in the shared workers case: what should happen when the top-level traversable is destroyed but the shared worker's owner set remains non-empty?

This is the easiest approach to spec and implement though.

General comments

Before reviewing this PR line by line and regardless of the issue above, some bigger picture points need to be settled:

  • It is generally a good idea to use WebDriver to provide fake/virtual/mock versions of the lowest level of your stack so that more of the real one is exercised.
    • Specifically, I am not convinced you need a "mock platform collector" on top of a virtual pressure source; instead, the spec needs to make a regular platform collector connect to a virtual pressure source when desired.
  • Related to the above, there needs to be a closer integration into the existing algorithms. For example:
  • What happens when a virtual source type is removed while one or more observers are active? Should they just stop receiving callbacks?
  • The data delivery model: should an update immediately notify the platform collector, or should it be stored and picked up by the platform collector at its sampling rate? This is normally an implementation detail, but with this API we have the problem of a potentially too slow sampling rate in production that the former option could help with.

index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
- there is one platform collector per global object (GO)
- a platform collector will use virtual sources for non-worker GOs
- virtual sources update data at a given sample rate set when created
- pressure observers collect data at their own given sample rate
@arskama
Copy link
Contributor

arskama commented May 2, 2024

  1. I find it a bit strange that the creation of the virtual source also defines the sample array.
    Should we restrict the creation to only create the virtual source? That would allow the user to control when the updates actually happen.

  2. Also we don't have a getter version, so we cannot check what was the set samplingInterval at creation.
    Should we have one Getter returning the existing virtual sources and their set samplingInterval?

  3. Should we have an example to show what needs to be done to for example set a new samplingInterval to a virtual source? Since apparently the virtual source needs to be deleted first? (right?)

Copy link
Member

@rakuco rakuco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the inline comments and discussions, let's summarize some pending items so we don't forget about them:

  • @JuhaVainio's point that it should be possible for a virtual pressure source to report itself as non-existent, so that observe() rejecting with NotSupportedError can be tested.
  • When an update's timestamp should be set when a virtual pressure source is being used.
  • What to do when "update virtual pressure source" is called before any observers are observing. The simplest option is to just ignore these updates; another option is to save either all or the latest and report it once the first observer starts observing.

index.html Outdated Show resolved Hide resolved
index.html Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
@rakuco
Copy link
Member

rakuco commented May 13, 2024

  1. I find it a bit strange that the creation of the virtual source also defines the sample array.
    Should we restrict the creation to only create the virtual source? That would allow the user to control when the updates actually happen.

This ended up being fixed a while ago.

  1. Also we don't have a getter version, so we cannot check what was the set samplingInterval at creation.
    Should we have one Getter returning the existing virtual sources and their set samplingInterval?

Getters are tricky because the information they return might be outdated by the time it reaches users. Unless really needed, I don't think we need to provide ways to access this information (which should be available to users anyway given that they made the WebDriver calls).

  1. Should we have an example to show what needs to be done to for example set a new samplingInterval to a virtual source? Since apparently the virtual source needs to be deleted first? (right?)

If we take the "let users handle the sampling rate" approach I mentioned in one of the inline comments, this might end up becoming a non-issue as a side-effect.

index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
index.html Outdated Show resolved Hide resolved
It was not being used anywhere; the source type is always when manipulating
the virtual pressure source mapping, which uses source types as keys.
This makes it more clear when writing the spec that this is a concept
related to a virtual pressure source rather than a general one.
…te algorithm

This makes it possible to invoke it from multiple locations in preparation
for supporting adding a virtual pressure source that reports itself as
non-existent.

While here: add `class="algorithm"` to the "data collection" algorithm.
This flag can be set in the "create virtual pressure source" endpoint, where
it is set to true by default.

When false, it causes calls to PressureObserver.observe() to reject with
NotSupportedError when attempting to use the given virtual pressure source.
This was copied from the Generic Sensor spec and not done in other places,
so drop the tag for uniformity.
… types"

This ensures that the types accepted in automation are the same which are
returned by `PressureObserver.knownSources`.

Whether this is really desired can be worked out later.
Copy link
Contributor

@arskama arskama left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If pressure source sample is now describing also "virtual pressure source" samples.

Would the definition of data require change?

The telemetry information provided by a pressure source is represented in this specification as a pressure source sample, a struct consisting of the following items:

data: contributing factors obtained from the underlying hardware or operating system.

or is test data being included in "operating system"

Copy link
Contributor

@arskama arskama left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If pressure source sample is now describing also "virtual pressure source" samples.

Would the definition of data require change?

The telemetry information provided by a pressure source is represented in this specification as a pressure source sample, a struct consisting of the following items:

data: contributing factors obtained from the underlying hardware or operating system.

or is test data being included in "operating system"

https://pr-preview.s3.amazonaws.com/kenchris/compute-pressure/pull/265.html#ref-for-dfn-pressure-source-1

@rakuco
Copy link
Member

rakuco commented Jun 13, 2024

If pressure source sample is now describing also "virtual pressure source" samples.

Would the definition of data require change?

Good point, I think allowing a PressureState there was too much of a stretch. I've made the definition clearer in commit d11d169 by saying data is a PressureState when the pressure source is a virtual one.

@rakuco
Copy link
Member

rakuco commented Jun 13, 2024

Alright, everything's been taken care of! The last bigger change is 93beaa0, which aligns the pressure type checks in the WebDriver endpoints with the same list of types used by PressureObserver.knownSources.

It does mean that one cannot add a virtual pressure source for a type that is not in knownSources. Whether that is really desirable can be changed by the editors later.

@rakuco rakuco changed the title Attempt to add Automation section and WebDriver support Automation section and WebDriver support Jun 14, 2024
@rakuco
Copy link
Member

rakuco commented Jun 14, 2024

There are a lot of changes in this PR as everyone can see. A lot of them are not in the newly-added Automation section, but in the rest where we had to provide less vague definitions for some concepts and make some of the algorithms less abstract.

I will file a tracking bug for the WebDriver work and split this PR into multiple ones to make the changes easier to understand in the future.

…pping

Avoid adding a platform collector with an empty associated pressure source
to the platform collector mapping.

Having observe() attempt to find a suitable platform collector every time in
this case is not that expensive, and _not_ doing it leads to a situation
where inactive observers still need to call unobserve() or disconnect() to
remove an entry from the platform collector mapping (to get observe() to try
to connect to a platform collector again, for example).
@arskama
Copy link
Contributor

arskama commented Jun 14, 2024

One major change we forgot in this PR:
Raphael as an Editor. :)

@kenchris
Copy link
Contributor Author

Indeed, I wanted to mention that in the meeting yesterday and totally forgot!

rakuco added a commit that referenced this pull request Jun 14, 2024
Related to #282: we need these algorithms to be properly defined in order to
be able to support WebDriver and fake pressure states.

This somewhat big change intends to clarify what "activate" and "deactivate"
data delivery actually mean, as there used to be just a "data delivery"
algorithm and no accompanying definitions for those two verbs. Furthermore,
the data delivery algorithm itself was confusing:
- It referenced a `data` variable in its declaration that was never passed
  by any callers.
- `data` was of an implementation-defined type and format, but the steps
  assumed it had some associated information like source type that was not
  set anywhere.

Fixing the above has required changes in different layers:
- The "platform collector" concept, which used to be an abstract entity
  with which all globals interacted to retrieve telemetry data for all
  source types, is now a per-global and per-source type concept.
  The lower-level concept that represents a cross-global interface for the
  hardware or OS is now a "pressure source", which contains a snapshot of
  the latest reading it has retrieved along with a timestamp.
- "Data delivery" is now called "data collection". It uses a platform
  collector and its associated pressure source to retrieve a telemetry
  sample that is transformed into a pressure state.
- There are algorithms for activating and deactivating data collection. Both
  ensure they data collection cannot be started/stopped if they have already
  been.
- `PressureObserver.observe()`'s had a "is not a valid source type" check
  that was too vague, as this step determined whether a given source type
  is supported by the platform or not, but the definition of "valid source
  type" was something else entirely.
  This step has been replaced by a sequence of steps that attempts to
  retrieve an existing platform collector for a source type and, if one does
  not exist, tries to connect to a corresponding pressure source. This
  change makes the same platform collector be used for all observers of a
  given source type and lays out in more detail what it means to check
  whether a source type is valid or not in this context.

Co-authored with @kenchris in #265. It was split off as a separate pull
request to make it easier to review and understand.
Usage so far had been inconsistent, with some places using the `!`
syntax for normative references and others not doing so.
rakuco added a commit that referenced this pull request Jun 14, 2024
#283)

Related to #282: we need these algorithms to be properly defined in order to
be able to support WebDriver and fake pressure states.

This somewhat big change intends to clarify what "activate" and "deactivate"
data delivery actually mean, as there used to be just a "data delivery"
algorithm and no accompanying definitions for those two verbs. Furthermore,
the data delivery algorithm itself was confusing:
- It referenced a `data` variable in its declaration that was never passed
  by any callers.
- `data` was of an implementation-defined type and format, but the steps
  assumed it had some associated information like source type that was not
  set anywhere.

Fixing the above has required changes in different layers:
- The "platform collector" concept, which used to be an abstract entity
  with which all globals interacted to retrieve telemetry data for all
  source types, is now a per-global and per-source type concept.
  The lower-level concept that represents a cross-global interface for the
  hardware or OS is now a "pressure source", which contains a snapshot of
  the latest reading it has retrieved along with a timestamp.
- "Data delivery" is now called "data collection". It uses a platform
  collector and its associated pressure source to retrieve a telemetry
  sample that is transformed into a pressure state.
- There are algorithms for activating and deactivating data collection. Both
  ensure they data collection cannot be started/stopped if they have already
  been.
- `PressureObserver.observe()`'s had a "is not a valid source type" check
  that was too vague, as this step determined whether a given source type
  is supported by the platform or not, but the definition of "valid source
  type" was something else entirely.
  This step has been replaced by a sequence of steps that attempts to
  retrieve an existing platform collector for a source type and, if one does
  not exist, tries to connect to a corresponding pressure source. This
  change makes the same platform collector be used for all observers of a
  given source type and lays out in more detail what it means to check
  whether a source type is valid or not in this context.

Co-authored with @kenchris in #265. It was split off as a separate pull
request to make it easier to review and understand.
rakuco added a commit that referenced this pull request Jun 14, 2024
Add WebDriver endpoints which allow manipulating virtual pressure sources,
which are pressure sources whose behavior and samples are entirelly
user-controlled. Also contrary to regular pressure sources, the provided
samples (or, in spec parlance, a virtual pressure source's latest sample's
data) are already PressureState instances rather than raw telemetry data
that will be transformed into an adjusted pressure state.

Caveats:
- Shared workers are unsupported at the moment (i.e. the WebDriver endpoints
  only have an effect on Window and DedicaredWorkerGlobalScope globals).
  Storing virtual pressure source information in a top-level traversable
  does not play well with shared workers, for which the concept is somewhat
  irrelevant.
  We need to think of a different solution in the future if support for
  shared workers is important.
- Once `PressureObserver.observe()` resolves, the same platform collector
  will be used until `disconnect()` or `unobserve()` are called. In other
  words, if a PressureObserver instance is active and using a real pressure
  source, adding a virtual pressure source of the same type will only have
  an effect on it and other instances in the same global once they all
  disconnect from the existing pressure source first.

In terms of changes to the existing algorithms and concepts:
- A top-level traversable has a mapping of source types to virtual pressure
  sources that is manipulated by the WebDriver endpoints.
- When creating a new platform collector, `PressureObserver.observe()` first
  attempts to use a virtual pressure source when one exists and can be used.
- The data collection algorithm distinguishes between the data format used
  by a virtual pressure source (which already is a PressureState) and by a
  real pressure source (which needs to be transformed into a PressureState).

Co-authored with @kenchris in #265. It was split off as a separate pull
request to make it easier to review and understand.

Fixes #282.
rakuco added a commit that referenced this pull request Jun 14, 2024
Add WebDriver endpoints which allow manipulating virtual pressure sources,
which are pressure sources whose behavior and samples are entirelly
user-controlled. Also contrary to regular pressure sources, the provided
samples (or, in spec parlance, a virtual pressure source's latest sample's
data) are already PressureState instances rather than raw telemetry data
that will be transformed into an adjusted pressure state.

Caveats:
- Shared workers are unsupported at the moment (i.e. the WebDriver endpoints
  only have an effect on Window and DedicaredWorkerGlobalScope globals).
  Storing virtual pressure source information in a top-level traversable
  does not play well with shared workers, for which the concept is somewhat
  irrelevant.
  We need to think of a different solution in the future if support for
  shared workers is important.
- Once `PressureObserver.observe()` resolves, the same platform collector
  will be used until `disconnect()` or `unobserve()` are called. In other
  words, if a PressureObserver instance is active and using a real pressure
  source, adding a virtual pressure source of the same type will only have
  an effect on it and other instances in the same global once they all
  disconnect from the existing pressure source first.

In terms of changes to the existing algorithms and concepts:
- A top-level traversable has a mapping of source types to virtual pressure
  sources that is manipulated by the WebDriver endpoints.
- When creating a new platform collector, `PressureObserver.observe()` first
  attempts to use a virtual pressure source when one exists and can be used.
- The data collection algorithm distinguishes between the data format used
  by a virtual pressure source (which already is a PressureState) and by a
  real pressure source (which needs to be transformed into a PressureState).

Co-authored with @kenchris in #265. It was split off as a separate pull
request to make it easier to review and understand.

Fixes #282.
@rakuco
Copy link
Member

rakuco commented Jun 14, 2024

The changes here have landed in #283 and #284. Closing.

@rakuco rakuco closed this Jun 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants