Skip to content

Commit

Permalink
fix(service-worker): allow creating post api requests after cache fai…
Browse files Browse the repository at this point in the history
…lure

Before creating a mutating http request, service-worker
invalidates lru cache entry and writes to cache storage.
Therefore, cache storage failure can prevent making post requests.
Fix this by catching and logging cache error, add a test case.

Fixes angular#33793
  • Loading branch information
apocalyp0sys committed Nov 21, 2019
1 parent eed1626 commit a8820d8
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
10 changes: 9 additions & 1 deletion packages/service-worker/worker/src/data.ts
Expand Up @@ -275,7 +275,15 @@ export class DataGroup {
return;
}
const table = await this.lruTable;
return table.write('lru', this._lru !.state);
try {
return table.write('lru', this._lru !.state);
} catch (err) {
// Writing lru cache table failed. This could be a result of a full storage.
// Continue serving clients as usual.
this.debugHandler.log(err, `DataGroup(${this.config.name}@${this.config.version}).syncLru`);
// TODO: Better detect/handle full storage; e.g. using
// [navigator.storage](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorStorage/storage).
}
}

/**
Expand Down
21 changes: 21 additions & 0 deletions packages/service-worker/worker/test/happy_spec.ts
Expand Up @@ -1330,6 +1330,27 @@ import {SwTestHarness, SwTestHarnessBuilder} from '../testing/scope';
server.assertSawRequestFor('/api-static/bar');
});

it('keeps serving mutating api requests when failing to write to cache',
// sw can invalidate LRU cache entry and try to write to cache storage on mutating request
async() => {
// Initialize the SW.
expect(await makeRequest(scope, '/foo.txt')).toEqual('this is foo');
await driver.initialized;
server.clearRequests();

// Make the caches unwritable.
spyOn(MockCache.prototype, 'put').and.throwError('Can\'t touch this');
spyOn(driver.debugger, 'log');
expect(await makeRequest(scope, '/api/foo', 'default', {
method: 'post'
})).toEqual('this is api foo');
expect(driver.state).toBe(DriverReadyState.NORMAL);
// Since we are swallowing an error here, make sure it is at least properly logged
expect(driver.debugger.log)
.toHaveBeenCalledWith(new Error('Can\'t touch this'), 'DataGroup(api@42).syncLru()');
server.assertSawRequestFor('/api/foo');
});

it('enters degraded mode when something goes wrong with the latest version', async() => {
await driver.initialized;

Expand Down

0 comments on commit a8820d8

Please sign in to comment.