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

Improve Activate with Try Activate #1065

Merged
merged 4 commits into from
Feb 16, 2017
Merged

Improve Activate with Try Activate #1065

merged 4 commits into from
Feb 16, 2017

Conversation

jungkees
Copy link
Collaborator

@jungkees jungkees commented Feb 3, 2017

This adds concepts and algorithms to track events (all service worker
events: lifecycle events, functional events, extendable message events)
that have pending extension promises so they can be used to check if the
registration's waiting worker can be promoted.

This also changes Install algorithm and related steps to match to the
implementations behavior. That is, instead of waiting for the promotion
condition in Install algorithm, newly introduced Try Activate algorithm
just tries to activate depending on the condition and return. Try
Activate is called when:

  • A service worker is installed.
  • The last client controlled by the existing active worker is unloaded.
  • skipWaiting() is called.
  • The extend lifetime promises for the existing active worker settle.

Related issue: #916.

This adds concepts and algorithms to track events (all service worker
events: lifecycle events, functional events, extendable message events)
that have pending extension promises so they can be used to check if the
registration's waiting worker can be promoted.

This also changes Install algorithm and related steps to match to the
implementations behavior. That is, instead of waiting for the promotion
condition in Install algorithm, newly introduced Try Activate algorithm
just tries to activate depending on the condition and return. Try
Activate is called when:
 - A service worker is installed.
 - The last client controlled by the existing active worker is unloaded.
 - skipWaiting() is called.
 - The extend lifetime promises for the existing active worker settle.

Related issue: #916.
@jungkees
Copy link
Collaborator Author

jungkees commented Feb 3, 2017

Chromium and Gecko implemented and shipped the resolution in #916 already. The spec follows with this PR. Please review.

/cc @mattto @wanderview @annevk @slightlyoff

docs/index.bs Outdated
@@ -168,6 +168,8 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe

A [=/service worker=] has an associated <dfn export id="dfn-set-of-event-types-to-handle">set of event types to handle</dfn> (a [=ordered set|set=]) whose [=item=] is an <a>event listener</a>'s event type. It is initially an empty set.

A [=/service worker=] has an associated <dfn export id="dfn-set-of-extended-events">set of extended events</dfn> (a [=ordered set|set=]) whose [=item=] is an [=event=]. It is initially an empty set.
Copy link
Contributor

Choose a reason for hiding this comment

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

Should [=event=] be {{ExtendableEvent}}?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that narrow typing would be better. Done.

@@ -364,6 +366,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
1. Else, let it be initialized to a new {{Client}} object that represents the worker associated with |incumbentGlobal|.
1. Let the {{ExtendableMessageEvent/ports}} attribute of |e| be initialized to |newPorts|.
1. <a>Dispatch</a> |e| at |destination|.
1. Invoke [=Update Service Worker Extended Events Set=] with |serviceWorker| and |e|.
Copy link
Contributor

Choose a reason for hiding this comment

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

So is this something every service worker event needs to do? Can we do this automatically when extendable events are created? Worried about every spec remembering to do this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We gate all the service worker events through Handle Fetch, Handle Foreign Fetch, Handle Functional Events, and ServiceWorker.postMessage(). So, maintenance would be okay. Also, I intended it to be called after dispatching an event returns.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I'm missing something. How would this work for push events?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Handle Functional Event runs https://github.com/w3c/ServiceWorker/pull/1065/files#diff-27b79860afe28f01aed4f1f6228367faR3082 after the callback steps given by other specs that are supposed to dispatch the functional events.

docs/index.bs Outdated
: Output
:: None

1. Assert: |registration|'s [=waiting worker=] is not null.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is called when promises passed to event.waitUntil settle, which can happen when there isn't a waiting worker, so isn't it common for the assertion to fail?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right. I missed that point. Made it return null when waiting worker is null there.

docs/index.bs Outdated
1. Set |redundantWorker| to |registration|'s <a>active worker</a>.
1. Wait for |redundantWorker| to finish handling any in-progress requests.
1. <a lt="Terminate Service Worker">Terminate</a> |redundantWorker|.
1. If |registration|'s [=active worker=] is not null, |redundantWorker| be |registration|'s [=active worker=].
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Missing let/set before |redundantWorker|?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Addressed.

docs/index.bs Outdated
1. If |registration|'s <a>active worker</a> is not null, then:
1. Set |redundantWorker| to |registration|'s <a>active worker</a>.
1. Wait for |redundantWorker| to finish handling any in-progress requests.
1. <a lt="Terminate Service Worker">Terminate</a> |redundantWorker|.
Copy link
Contributor

Choose a reason for hiding this comment

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

When are these workers terminated now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought it would be not needed when Try Activate successfully called Activate. But you're right. It'd be safer to call Terminate Service Worker before get it redundant. In the follow-up commit, I addressed this point and also moved steps for invoking Update Worker State for the redundant works up, which both Chromium and Gecko do.

@@ -3100,6 +3122,21 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
</section>

<section algorithm>
<h3 id="update-service-worker-extended-events-set-algorithm"><dfn>Update Service Worker Extended Events Set</dfn></h3>
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a little worried about the lifecycle of this, but I might be worrying over nothing.

If a service worker abruptly terminates (due to long-running tasks or whatever), what happens to these events? Should we clear the set of extended events on service worker terminate?

I guess we'll need to handle timeouts to waitUntil extension promises at some point.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good point! I added a step to Terminate Service Worker to remove all the items in the service worker's set of extended events.

For extended events, I thought we decided to leave them run to completion: #916 (comment). So, I removed the steps that abort the in-progress requests.

To clarify what happens when a service worker abruptly terminates, Terminate Service Worker resets the set of extended events to an empty set (done in this PR), retains the tasks (for functional events) in the queue so the next worker run will execute them.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, I missed that. Sounds good!

@jungkees
Copy link
Collaborator Author

jungkees commented Feb 8, 2017

@jakearchibald, thanks for review! I uploaded a follow-up commit. PTAL.

@jungkees jungkees merged commit f1a1120 into master Feb 16, 2017
@jungkees jungkees deleted the improve-activate-fix branch February 16, 2017 09:58
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Sep 4, 2017
According to the latest spec, the skipWaiting promise should be resolved
after 'activate' event is dispatched. This change is from
w3c/ServiceWorker#1065.

Tracing through the spec, skipWaiting() enters "Try Activate".
"Try Activate" invokes "Activate". "Activate" blocks until the final step:
"13. Run the Update Worker State algorithm passing registration’s active
worker and activated as the arguments."

"Update Worker State" queues a task to set ServiceWorker#state to 'activated'.
But in step 10, we have dispatched the 'activate' event. Therefore the order
should be:
1. 'activate' event handler runs
2. skipWaiting() promise resolves
3. ServiceWorker#state is set to 'activated'

So we correct the test case here and delete all the wrong expected files.

BUG=725616

Change-Id: Id0765988c7cdf48f39bb73ccb3fc0cce6ea60949
Reviewed-on: https://chromium-review.googlesource.com/646244
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#499513}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Sep 4, 2017
According to the latest spec, the skipWaiting promise should be resolved
after 'activate' event is dispatched. This change is from
w3c/ServiceWorker#1065.

Tracing through the spec, skipWaiting() enters "Try Activate".
"Try Activate" invokes "Activate". "Activate" blocks until the final step:
"13. Run the Update Worker State algorithm passing registration’s active
worker and activated as the arguments."

"Update Worker State" queues a task to set ServiceWorker#state to 'activated'.
But in step 10, we have dispatched the 'activate' event. Therefore the order
should be:
1. 'activate' event handler runs
2. skipWaiting() promise resolves
3. ServiceWorker#state is set to 'activated'

So we correct the test case here and delete all the wrong expected files.

BUG=725616

Change-Id: Id0765988c7cdf48f39bb73ccb3fc0cce6ea60949
Reviewed-on: https://chromium-review.googlesource.com/646244
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#499513}
MXEBot pushed a commit to mirror/chromium that referenced this pull request Sep 5, 2017
According to the latest spec, the skipWaiting promise should be resolved
after 'activate' event is dispatched. This change is from
w3c/ServiceWorker#1065.

Tracing through the spec, skipWaiting() enters "Try Activate".
"Try Activate" invokes "Activate". "Activate" blocks until the final step:
"13. Run the Update Worker State algorithm passing registration’s active
worker and activated as the arguments."

"Update Worker State" queues a task to set ServiceWorker#state to 'activated'.
But in step 10, we have dispatched the 'activate' event. Therefore the order
should be:
1. 'activate' event handler runs
2. skipWaiting() promise resolves
3. ServiceWorker#state is set to 'activated'

So we correct the test case here and delete all the wrong expected files.

BUG=725616

Change-Id: Id0765988c7cdf48f39bb73ccb3fc0cce6ea60949
Reviewed-on: https://chromium-review.googlesource.com/646244
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#499513}
rachelandrew pushed a commit to rachelandrew/web-platform-tests that referenced this pull request Nov 8, 2017
According to the latest spec, the skipWaiting promise should be resolved
after 'activate' event is dispatched. This change is from
w3c/ServiceWorker#1065.

Tracing through the spec, skipWaiting() enters "Try Activate".
"Try Activate" invokes "Activate". "Activate" blocks until the final step:
"13. Run the Update Worker State algorithm passing registration’s active
worker and activated as the arguments."

"Update Worker State" queues a task to set ServiceWorker#state to 'activated'.
But in step 10, we have dispatched the 'activate' event. Therefore the order
should be:
1. 'activate' event handler runs
2. skipWaiting() promise resolves
3. ServiceWorker#state is set to 'activated'

So we correct the test case here and delete all the wrong expected files.

BUG=725616

Change-Id: Id0765988c7cdf48f39bb73ccb3fc0cce6ea60949
Reviewed-on: https://chromium-review.googlesource.com/646244
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#499513}
jakearchibald pushed a commit to jakearchibald/web-platform-tests that referenced this pull request Nov 16, 2017
According to the latest spec, the skipWaiting promise should be resolved
after 'activate' event is dispatched. This change is from
w3c/ServiceWorker#1065.

Tracing through the spec, skipWaiting() enters "Try Activate".
"Try Activate" invokes "Activate". "Activate" blocks until the final step:
"13. Run the Update Worker State algorithm passing registration’s active
worker and activated as the arguments."

"Update Worker State" queues a task to set ServiceWorker#state to 'activated'.
But in step 10, we have dispatched the 'activate' event. Therefore the order
should be:
1. 'activate' event handler runs
2. skipWaiting() promise resolves
3. ServiceWorker#state is set to 'activated'

So we correct the test case here and delete all the wrong expected files.

BUG=725616

Change-Id: Id0765988c7cdf48f39bb73ccb3fc0cce6ea60949
Reviewed-on: https://chromium-review.googlesource.com/646244
Commit-Queue: Matt Falkenhagen <falken@chromium.org>
Reviewed-by: Matt Falkenhagen <falken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#499513}
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.

2 participants