mbleigh/escapable-amp

Possibility for Stale Content

Closed this issue · 2 comments

I really like the idea you describe about Evented Rendering here: https://youtu.be/7_2CJs_VZk4?t=1720

Maybe I'm missing something, but wouldn't it be possible to end up with stale contend for a whole year (worst case) in your example? I see the following scenario:

  1. A region gets updated.
  2. updateRegionPage() is called. This prerenders the page.
  3. writeAndPurge() is called. This writes the prerendered page to Cloud Storage and purges the page on Firebase Hosting.
  4. The next time the page is requested, Firebase Hosting serves it from Cloud Storage via Cloud Functions (with a CDN cache s-maxage of one year).

Imagine that while the Cloud Function in step 4 is running, the region gets updated a second time which starts the process again. The following could be possible:

(Process 1): Is not finished with step 4. It already has the stale page from Cloud Storage but hasn't served it yet.
(Process 2): Goes through step 3. It prerenders and purges the page.
(Process 1): Finishes with step 4. This means that Firebase Hosting serves the stale page and caches it for a year.

I don't know how likely this is but it would be quite bad if it happens since it is really hard to find the bug and the client has no possibility to get the correctly rendered page for potentially a whole year.

I hope that I'm wrong. Or is there anything you could do about that?

You're right that there is a very small chance of staleness with the current code. There are a few different ways to handle this kind of issue, but the one I would probably take would be something like:

  1. Create a collection called renders whose documents will have two fields: path and started.
  2. When performing an evented render, transactionally check to see if there is already a render in the collection that started less than (function timeout) ago.
  3. If not, write one there with the current timestamp.
  4. If so, wait 1s and try again.
  5. When the render completes, erase the document from the renders collection.

This essentially provides a path-level locking mechanism to make sure that writes are performed sequentially. You could get even fancier here with document change timestamps to ensure that writes are performed in order.

This would be a good idea for a robust, large-scale application with many potential editors, but I don't think it's going to be necessary for this little demo app 😄

Thank you for this answer @mbleigh. That helps me understand and find a solution.