Skip to content

Commit

Permalink
[bugfix beta] Fetch cancels unload
Browse files Browse the repository at this point in the history
When fetching records, cancel internal model destruction if it is
scheduled, ie if the model is dematerializing because it was unloaded.

It is not possible to construct snapshots for dematerializing internal
models.  Prior to this commit, this could happen when fetching a record
in the same runloop that it was unloaded.  A straightfoward way of
getting into this state was via

```
store.findRecord('book', 1).then(b => b.unloadRecord)
```

when the model is already cached in the store.  Under these conditions,
the fetch is scheduled, then the promise fulfills with the cached record
and is unloaded and *then* the scheduled fetch is flushed.

[fix #5343]
  • Loading branch information
hjdivad committed Mar 14, 2018
1 parent 872f015 commit 7444444
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
12 changes: 12 additions & 0 deletions addon/-private/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,18 @@ Store = Service.extend({
seeking[internalModel.id] = pendingItem;
}

for (let i = 0; i < totalItems; i++) {
let internalModel = internalModels[i];
// We may have unloaded the record after scheduling this fetch, in which
// case we must cancel the destory. This is because we require a record
// to build a snapshot. This is not fundamental: this cancelation code
// can be removed when snapshots can be created for internal models that
// have no records.
if (internalModel.hasScheduledDestroy()) {
internalModels[i].cancelDestroy();
}
}

function _fetchRecord(recordResolverPair) {
let recordFetch = store._fetchRecord(
recordResolverPair.internalModel,
Expand Down
28 changes: 28 additions & 0 deletions tests/integration/records/unload-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2089,3 +2089,31 @@ test('unload invalidates link promises', function(assert) {
})
);
});

test('fetching records cancels unloading', function(assert) {
env.adapter.findRecord = (store, type, id) => {
assert.equal(type, Person, 'findRecord(_, type) is correct');
assert.deepEqual(id, '1', 'findRecord(_, _, id) is correct');

return {
data: {
id: 1,
type: 'person'
}
}
};

run(() =>
env.store.push({
data: {
id: 1,
type: 'person'
}
})
);

return run(() =>
env.store.findRecord('person', 1, { backgroundReload: true })
.then(person => person.unloadRecord())
);
});

0 comments on commit 7444444

Please sign in to comment.