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

When should implementations serialize caches? #362

Closed
gavinp opened this issue Jul 7, 2014 · 15 comments
Closed

When should implementations serialize caches? #362

gavinp opened this issue Jul 7, 2014 · 15 comments

Comments

@gavinp
Copy link

gavinp commented Jul 7, 2014

Currently, cache.add() is described in the spec as being placed in the [[RequestToResponseMap]] when the response first resolves. There's no way to use cache.put() earlier than response resolution, since the spec doesn't permit passing a promise to the contructor for the response argument.

When the response resolves is somewhat implementation dependent; but it can be as early as when headers are received for the final, non-redirect response for the request; since the data is in a blob behind a promise, the response can be resolved before the full data is received.

When should a Cache API implementation be fully committed to disk?

A common pattern of use is likely to be that a ServiceWorker creates a new cache, loads a series of resources in to it, and moves the new cache on top of the existing cache as a replacement. Example:

var newCache = caches.add("newOfflineCache");
var toLoadRequests = ...;
Promise(toLoadRequests.map(newCache.add, newCache)).then(function() {
  return caches.rename("newOfflineCache", "OfflineCache");
});

But this rename isn't quite safe, is it? The requests are only guaranteed to have received headers, not bodies, and so if we do the rename, we risk partial/erroneous/missing responses in the renamed cache?

I am left with a few questions:

  • When should implementations finalize serializing an entry to disk, so it is likely to be found in subsequent uses of that Cache?
  • Should caches.rename() and others wait for all in-flight requests to reach this point before resolving?
  • Why isn't this mechanism exposed as part of the Cache API?
@gavinp
Copy link
Author

gavinp commented Jul 7, 2014

(Is this a duplicate of issue #313 ?)

@jakearchibald
Copy link
Contributor

If a server gives us <body> Hello wo, can we tell it was intending to send more? I was under the impression we couldn't, that's why "successful headers" as the resolve point.

A common pattern of use is likely to be that a ServiceWorker creates a new cache, loads a series of resources in to it, and moves the new cache on top of the existing cache as a replacement.

I think it's useful to be able to do that, but I'm not sure it's common. I've been going with:

  1. During install, create caches named 'mysite-v2-stuff', 'mysite-v2-otherstuff' & populate
  2. During activate, remove caches named 'mysite-v[^2][^-]'

…although I guess the rename way becomes more useful for full cache replacements outside of the serviceworker update process.

@jakearchibald
Copy link
Contributor

Done a bit of research around this:

Loading a page with Content-Length < actual content length

  • Chrome: Truncated content - no indication of error
  • Firefox: Truncated content - no indication of error
  • Safari: Truncated content - no indication of error
  • IE: Truncated content - no indication of error

Loading a page with Content-Length > actual content length

  • Chrome: Rendered received content, spinner until timeout, ERR_CONTENT_LENGTH_MISMATCH & ERR_CACHE_MISS in console
  • Firefox: No in-progress render, spinner until timeout, rendered received content, no console errors
  • Safari: No in-progress render, spinner until timeout, no final render, "Failed to load resource: The network connection was lost." in console
  • IE: No in-progress render, spinner until timeout, rendered received content, no console errors

Loading a page with Content-Length > actual content length ending in abrupt server termination

  • Chrome: Received content rendered, ERR_CONTENT_LENGTH_MISMATCH in console
  • Firefox: Received content rendered, no errors
  • Safari: No content render "Safari can’t open the page “‎localhost:3000/app-name/” because the server unexpectedly dropped the connection."
  • IE: Received content rendered, no errors

Loading a page with no Content-Length, chunked encoding & abrupt server termination

  • Chrome: Received content rendered, ERR_INCOMPLETE_CHUNKED_ENCODING in console
  • Firefox: Received content rendered, no errors
  • Safari: Received content rendered, no errors
  • IE: Received content rendered, no errors

XHR a page with Content-Length < actual content length

  • Chrome: load event, truncated content
  • Firefox: load event, truncated content
  • Safari: load event, truncated content
  • IE: load event, truncated content

XHR a page with Content-Length > actual content length

  • Chrome: waits until timeout, error event, ERR_CONTENT_LENGTH_MISMATCH in console
  • Firefox: waits until timeout, load event, received content delivered
  • Safari: waits until timeout, error event, "Failed to load resource: The network connection was lost." in console
  • IE: waits until timeout, load event, received content delivered

XHR a page with Content-Length > actual content length ending in abrupt server termination

  • Chrome: error event, ERR_CONTENT_LENGTH_MISMATCH in console
  • Firefox: load event, received content delivered
  • Safari: error event, "Failed to load resource: The network connection was lost." in console
  • IE: load event, received content delivered

XHR a page with no Content-Length, chunked encoding & abrupt server termination

  • Chrome: error event, ERR_INCOMPLETE_CHUNKED_ENCODING in console
  • Firefox: load event, received content delivered
  • Safari: load event, received content delivered
  • IE: load event, received content delivered

@astanley
Copy link

Amazing summary, Jake.

@dubravkoL
Copy link

Thanks a lot! ;)

@Spudley
Copy link

Spudley commented Jul 17, 2014

Useful bit of research. Thank you. One question: Are these results consistent across browser versions or did you just test the latest version of each?

@jakearchibald
Copy link
Contributor

Only looked at the latest stable versions of each

@SKing7
Copy link

SKing7 commented Jul 17, 2014

cool,how do you test these?

@jakearchibald
Copy link
Contributor

@SKing7 just a little nodejs server sending the headers & data

@jakearchibald
Copy link
Contributor

Update: Latest thinking is to resolve on full stream read, allowing for rejection on detectable errors

@wanderview
Copy link
Member

Update: Latest thinking is to resolve on full stream read, allowing for rejection on detectable errors

Just to clarify, how does this effect a Match() while the Put() stream is still in process? Can a Match() for a request/response pair succeed prior to the Put() promise resolving?

// ignore returned promise
cache.put(request, fetchResponse);

// match request before put() would have resolved.  Should this reject or
// resolve with clone of incomplete fetchResponse above?
cache.match(request);

I think my first implementation will have the Match() reject in this case.

@KenjiBaheux
Copy link
Collaborator

Talked to Gavin, this issue covers rather convoluted edge cases and does not qualify as "impact MVP"

@KenjiBaheux
Copy link
Collaborator

We'll go with the current thinking. Tracked via crbug.com/392621 for Blink.

@jungkees
Copy link
Collaborator

jungkees commented Jul 7, 2015

I think we finally settled on this behavior: #573 (comment). (See also #361 (comment)). If there's no more concern, I'd be happy to close the related issues.

@jungkees
Copy link
Collaborator

jungkees commented Jul 8, 2015

Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants