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

add option to configure when shoebox data expires #369

Merged
merged 2 commits into from
Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}
```