Skip to content

Commit

Permalink
add option to configure when shoebox data expires (#369)
Browse files Browse the repository at this point in the history
* remove unneeded dependency
* add option to configure when shoebox data expires
  • Loading branch information
st-h authored Jun 18, 2020
1 parent 1a17a9b commit 0f0e871
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
25 changes: 22 additions & 3 deletions addon/mixins/fastboot-adapter.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable ember/no-new-mixins */

import Mixin from '@ember/object/mixin';
import { inject as service } from '@ember/service';
import { resolve } from 'rsvp';
import { cacheKey, shoeboxize } from 'ember-data-storefront/-private/utils/get-key';

import { getOwner } from '@ember/application';
/**
This mixin adds fastboot support to your data adapter. It provides no
public API, it only needs to be mixed into your adapter.
Expand All @@ -28,6 +30,13 @@ export default Mixin.create({
fastboot: service(),
storefront: service(),

init() {
this._super(...arguments);
if (this.fastboot.isFastBoot) {
this.set('storefront.fastbootShoeboxCreated', new Date());
}
},

ajax(url, type, options = {}) {
let cachedPayload = this._getStorefrontBoxedQuery(type, url, options.data);
let maybeAddToShoebox = this._makeStorefrontQueryBoxer(type, url, options.data);
Expand Down Expand Up @@ -59,13 +68,23 @@ export default Mixin.create({
let shoebox = fastboot && fastboot.get('shoebox');
let box = shoebox && shoebox.retrieve('ember-data-storefront');

const config = getOwner(this).resolveRegistration('config:environment');
const maxAgeMinutes = config.storefront ? config.storefront.maxAge : undefined;

if (!isFastboot && box && box.queries && Object.keys(box.queries).length > 0) {
const valid = this.isDateValid(box.created, maxAgeMinutes);
let key = shoeboxize(cacheKey([type, url.replace(/^.*\/\/[^\/]+/, ''), params]));
payload = box.queries[key];

if (valid) {
payload = box.queries[key];
}
delete box.queries[key];
}

return payload;
}
},

isDateValid(createdString, maxAgeMinutes) {
return (new Date() - new Date(createdString)) / 1000 / 60 < maxAgeMinutes;
}
})
3 changes: 3 additions & 0 deletions fastboot/instance-initializers/ember-data-storefront.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export function initialize(applicationInstance) {
let storefront = applicationInstance.lookup('service:storefront');

shoebox.put('ember-data-storefront', {
get created() {
return storefront.get('fastbootShoeboxCreated');
},
get queries() {
return storefront.get('fastbootDataRequests');
}
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
"ember-cli-eslint": "^5.1.0",
"ember-cli-fastboot": "^2.0.4",
"ember-cli-htmlbars": "^4.0.1",
"ember-cli-htmlbars-inline-precompile": "^3.0.0",
"ember-cli-inject-live-reload": "^1.8.2",
"ember-cli-mirage": "1.1.6",
"ember-cli-qunit": "^4.3.2",
Expand Down
13 changes: 13 additions & 0 deletions tests/dummy/app/pods/docs/guides/fastboot/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,16 @@ The `FastbootAdapter` works by storing the results of AJAX requests into fastboo
The adapter will delete queries from the shoebox as soon as they are used. This ensures that if your application ever tries to re-make a network request in the future, it will not be served a cached version.

Fastboot rendered pages need to be generated quickly, since they are rendered on the server in an HTTP request-resposne cycle. Because of this, they tend to not make many network requests. This means that a few seconds after the browser re-renders a fastboot page, the query cache should be empty since the client rendered application will have re-fetched all of the fastboot data.

## Configure an expiration date

In certain cases, like the browser restoring its session, a cached version of the index.html page may be served, which contains shoebox data from the initial, cached request. The adapter is not aware that this data is stale, and outdated information is displayed to the user. To prevent this you can configure a duration after which data will no longer be served from the shoebox.

```
// config/environment.js
ENV = {
storefront: {
maxAge: 10 // shoebox expires 10 minutes after the fastboot server has rendered the page
}
}
```

0 comments on commit 0f0e871

Please sign in to comment.