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

Throwing error instead of re registering sync on failure #1155

Merged
merged 5 commits into from
Jan 8, 2018

Conversation

prateekbh
Copy link
Collaborator

@prateekbh prateekbh commented Jan 4, 2018

R: @philipwalton
CC: @jeffposnick @addyosmani @gauntface

Fixes #1145

Currently, on any failures in queue replay it results in re-registering of sync queue tag.
This causes infinite loop in case of offline from devtools + IIRC will not re-play the failed requests as this will re-register the same tag and also resolve the promise inside event.waitUntil of sync event. Hence telling the browser that we've successfully done everything related to this tag.

Instead to indicate any failure it is require that the promise passed to event.waitUntil should be rejected. ref: https://github.com/WICG/BackgroundSync/blob/master/explainer.md#the-api

The promise passed to waitUntil is a signal to the user agent that the sync event is ongoing and that it should keep the service worker alive if possible. Rejection of the event signals to the user agent that the sync failed. Upon rejection the user agent should reschedule (likely with a user agent determined backoff).

@prateekbh prateekbh requested a review from philipwalton January 4, 2018 22:52
@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 2e6c392 on bgSyncRetryFix into ** on v3**.

if (failedRequests.length) {
await Promise.all(failedRequests.map((storableRequest) => {
return this._queueStore.addEntry(storableRequest);
}));

await this._registerSync();
return Promise.reject(failedRequests);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: can we throw here instead of returning a rejected promise? I think it's better to use async function patterns when inside an async function (rather that promise patterns).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

so throw new Error(failedRequests);?

Copy link
Member

Choose a reason for hiding this comment

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

I was thinking just:

throw failedRequests;

In JS you can throw any value.

cc: @gauntface and @jeffposnick to see if they have thoughts on this.

In general I think we should stick to the pattern that async function use await, try, catch, and throw, and regular functions use resolve and reject, though I guess this may be a bit of a special case...

Copy link
Contributor

Choose a reason for hiding this comment

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

Does anything end up consuming the rejected promise that's returned by this function? Or is the fact that it's a rejected promise all that matters, with the rejection value ignored?

If the value is ignored, then I'd rather see

throw new Error('<some meaningful message>');

so that a developer reading the source has a bit more context. And if at some point in the future logging is added in, it will end up with a meaningful log message.

If the value isn't ignored, and it needs to be that array, then using Promise.reject() seems fine to me, but I'd ask that you add in a comment explaining what's going on.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah nothing really consumes it.

  • i was thinking something likethrow new Error('X number of requests failed');

Choose a reason for hiding this comment

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

Please use a WorkboxError.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

return;
}

return Promise.reject('should have exit from catch');
Copy link
Member

Choose a reason for hiding this comment

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

Same as above, can we throw here instead of returning a rejected promise?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

expect(self.registration.sync.register.calledOnce).to.be.true;
expect(self.registration.sync.register.calledWith(
'workbox-background-sync:foo')).to.be.true;
return Promise.reject('should have exit from catch');
Copy link
Member

Choose a reason for hiding this comment

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

Same as above, can we throw here instead of returning a rejected promise?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

// If any requests failed, put the failed requests back in the queue
// and register for another sync.
// and reject promise.
Copy link
Member

Choose a reason for hiding this comment

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

Maybe reword this to: "and rethrow the failed requests"?

Note: this comment I'm less concerned about changing...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

@prateekbh
Copy link
Collaborator Author

@philipwalton correct me if I am wrong, but throw new Error... can only take string as param. So tops we can pass back is how many requests failed. and not the actual requests

@philipwalton
Copy link
Member

Plain Error objects can only take a string, but AFAIK in JS you can throw any value. See #1155 (comment) for my comments.

@gauntface gauntface added the Chillin' Not being actively worked on, or deferred for a point in the future. label Jan 5, 2018
@gauntface
Copy link

As Jeff pointed out - we should be using useful information to explain what is happening if a developer is viewing this.

The scenario you described sounds like an expected and valid scenario (i.e. the request failed to work - no worries, we'll still have the sync set up). For this - use a WorkboxError with a valid string to explain what has happened.

This means the developer will know the error is from Workbox (because it's a WorkboxError) and the message will highlight this is expected and not to worry.

@gauntface gauntface removed the Chillin' Not being actively worked on, or deferred for a point in the future. label Jan 5, 2018
@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 6c48088 on bgSyncRetryFix into ** on v3**.

@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 6c48088 on bgSyncRetryFix into ** on v3**.

@prateekbh prateekbh changed the title [WIP] Throwing error instead of re registering sync on failure Throwing error instead of re registering sync on failure Jan 5, 2018
return;
}

throw new Error('should have exit from catch');

Choose a reason for hiding this comment

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

Could you use the helper: https://github.com/GoogleChrome/workbox/blob/v3/infra/testing/expectError.js

This will check the error is a WorkboxError with an expected code and it returns a promise, so you can await for the response and check the object store entries after.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

try {
await queue.replayRequests(); // The second request should fail.
} catch (error) {
expect(error).to.be.instanceof(WorkboxError);

Choose a reason for hiding this comment

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

Please use expectError helper here as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

expect(self.registration.sync.register.calledOnce).to.be.true;
expect(self.registration.sync.register.calledWith(
'workbox-background-sync:foo')).to.be.true;
throw new Error('should have exit from catch');

Choose a reason for hiding this comment

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

This wont be needed after switching to expectError().

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

@@ -376,7 +382,13 @@ describe(`[workbox-background-sync] Queue`, function() {

await queue.addRequest(new Request('/three'));
await queue.addRequest(new Request('/four'));
await queue.replayRequests();
try {
await queue.replayRequests();

Choose a reason for hiding this comment

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

Please use expectError here and make sure the error is what you expect.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

Copy link

@gauntface gauntface left a comment

Choose a reason for hiding this comment

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

Could you switch to expectError() helper throughout the tests to ensure everything runs as we expect after future changes.

@workbox-pr-bot
Copy link
Collaborator

PR-Bot Size Plugin

Changed File Sizes

File Before After Change GZipped
packages/workbox-background-sync/build/workbox-background-sync.prod.js 3.15 KB 3.21 KB +2% 1.38 KB
packages/workbox-broadcast-cache-update/build/workbox-broadcast-cache-update.prod.js 1.06 KB 1.06 KB -0% 565 B
packages/workbox-cache-expiration/build/workbox-cache-expiration.prod.js 3.27 KB 3.23 KB -1% 1.20 KB
packages/workbox-cacheable-response/build/workbox-cacheable-response.prod.js 591 B 590 B -0% 343 B
packages/workbox-core/build/workbox-core.prod.js 6.38 KB 6.36 KB -0% 2.52 KB
packages/workbox-google-analytics/build/workbox-google-analytics.prod.js 1.92 KB 1.92 KB -0% 999 B
packages/workbox-precaching/build/workbox-precaching.prod.js 5.18 KB 5.18 KB -0% 2.02 KB
packages/workbox-range-requests/build/workbox-range-requests.prod.js 1.66 KB 1.65 KB -0% 814 B
packages/workbox-routing/build/workbox-routing.prod.js 2.77 KB 2.74 KB -1% 1.24 KB
packages/workbox-strategies/build/workbox-strategies.prod.js 3.24 KB 3.23 KB -0% 1.00 KB
packages/workbox-sw/build/workbox-sw.js 1.46 KB 1.46 KB -0% 794 B

New Files

No new files have been added.

All File Sizes

View Table
File Before After Change GZipped
packages/workbox-background-sync/build/workbox-background-sync.prod.js 3.15 KB 3.21 KB +2% 1.38 KB
packages/workbox-broadcast-cache-update/build/workbox-broadcast-cache-update.prod.js 1.06 KB 1.06 KB -0% 565 B
packages/workbox-build/build/_types.js 41 B 41 B 0% 61 B
packages/workbox-build/build/index.js 2.52 KB 2.52 KB 0% 1.06 KB
packages/workbox-cache-expiration/build/workbox-cache-expiration.prod.js 3.27 KB 3.23 KB -1% 1.20 KB
packages/workbox-cacheable-response/build/workbox-cacheable-response.prod.js 591 B 590 B -0% 343 B
packages/workbox-cli/build/app.js 4.57 KB 4.57 KB 0% 1.65 KB
packages/workbox-cli/build/bin.js 2.53 KB 2.53 KB 0% 1.07 KB
packages/workbox-core/build/workbox-core.prod.js 6.38 KB 6.36 KB -0% 2.52 KB
packages/workbox-google-analytics/build/workbox-google-analytics.prod.js 1.92 KB 1.92 KB -0% 999 B
packages/workbox-precaching/build/workbox-precaching.prod.js 5.18 KB 5.18 KB -0% 2.02 KB
packages/workbox-range-requests/build/workbox-range-requests.prod.js 1.66 KB 1.65 KB -0% 814 B
packages/workbox-routing/build/workbox-routing.prod.js 2.77 KB 2.74 KB -1% 1.24 KB
packages/workbox-strategies/build/workbox-strategies.prod.js 3.24 KB 3.23 KB -0% 1.00 KB
packages/workbox-sw/build/workbox-sw.js 1.46 KB 1.46 KB -0% 794 B
packages/workbox-webpack-plugin/build/generate-sw.js 5.84 KB 5.84 KB 0% 2.04 KB
packages/workbox-webpack-plugin/build/index.js 742 B 742 B 0% 470 B
packages/workbox-webpack-plugin/build/inject-manifest.js 7.95 KB 7.95 KB 0% 2.65 KB

Workbox Aggregate Size Plugin

☠️ WARNING ☠️

We are using 152% of our max size budget.

Total Size: 22.27KB
Percentage of Size Used: 152%

Gzipped: 8.9KB

@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 274bb31 on bgSyncRetryFix into ** on v3**.

@gauntface gauntface merged commit 36e99bd into v3 Jan 8, 2018
@gauntface gauntface deleted the bgSyncRetryFix branch January 8, 2018 19:38
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.

6 participants