isomerpages / isomercms-backend

A static website builder and host for the Singapore Government
5 stars 1 forks source link

feat(etags): implement ETags #773

Closed seaerchin closed 1 year ago

seaerchin commented 1 year ago

Problem

Currently, Isomer uses a huge amount of tokens due to not caching. This leads to scaling issue, where our github token limits are quickly reached and users are unable to access the CMS.

Closes IS-172

Solution

  1. use an external package axios-cache-interceptor to utilise ETags for cache. See here for info on etags.
    • note that this is using in memory storage. the implications are that: we could potentially have some requests that could be cached but are not (current ETag value is 1 -> user A edits -> ETag value now 2 -> other instance doesn't knows -> queries from other instance -> ETag value updated)
    • potential for stale reads - github will tell us if the old etag value is outdated or not (ie, return 200) but the package uses the cache-control header to control freshness (which is good). because github's header sets max-age=60, the package will internally use the old value for 60s.

Tests

  1. first, add a console.log for remainingRequests into respHandler for AxiosInstance.ts, so that we know how much requests are remaining
  2. next, issue a GET request to the e2e-test-repo's homepage (curl --request GET \ --url http://localhost:8081/v2/sites/e2e-test-repo/homepage)
  3. observe the # of requests remaining.
  4. repeat steps 2-3; the # of requests remaining should be unchanged
  5. make an edit on the homepage
  6. repeat steps 2-3, the # of requests should be unchanged if it's less than a minute
  7. update the page again
  8. do steps 2-3, the request should succeed

New dependencies:

Deploy notes

  1. axios got upgraded from 0.21.x to 0.25.0
    • list of breaking changes here
    • went through most of them, mostly typing changes.
  2. had to use 0.9.2 as a minimum for axios-cache-interceptor
    • see compat chart here
    • this is because of 2 reasons - ETag functionality only added in 0.6 + their import for object-code is an outdated one, which doesn't get fixed till 0.9.2.