ember-data-model-fragments
ember-data-model-fragments copied to clipboard
can't unload/destroy fragments?
Not sure if this is a bug or desired feature, but If I do the following:
fragment = this.get('store').createFragment('thingy')
fragment.unloadRecord()
I get the error:
EmberError {description: undefined, fileName: undefined, lineNumber: undefined, message: "Attempted to handle event `unloadRecord` on <garaj…:ember2843:> while in state root.loaded.created. ", name: "Error"…}
Should the record be just removed?
Definitely not ideal behavior 🙈
I assume what you're trying to accomplish is to release the fragment from the store so it can be GC'd. Since fragments don't have unique ids, there's no identity map in the store like there is for models, only references from models to fragments. This makes unloading the fragment basically a no-op, so really you can just .destroy()
the fragment and never look back (assuming it's not referenced by a record).
Note that destroying unreferenced fragments is actually really important. Since there's no back-door references to fragments in the store, there's no way to clean them up automatically like models. Fragments that are referenced by models are destroyed automatically in the model's willDestroy
hook (see #175), but fragments that aren't referenced by a model are never GC'd unless they are manually destroyed. This doesn't usually affect app performance, but it can have a significant impact on test suites where fragments are abandoned in a common code path.
I'm curious what you think would be better behavior of Fragment#unloadRecord
:
- No-op
- No-op with console warning
-
Ember.assert
@slindberg 3 Ember.assert
since it leads to leaking objects.
We are experiencing some hardship with this and wonder if anything has been or could be done about it. We are using model fragments, and our data updates frequently. We unload the model data from the store for the model that the fragments are included in to keep the memory footprint down. However, the model fragments as shown in the Ember inspector don’t appear to unload with their parent so appear to grow infinitely. It also doesn’t seem to be possible to do a store.unloadAll on the fragments. So is the only solution to iterate over all the fragments and do a destroy() on each? Or is there another solution?
Currently experiencing same issue as @GeekSMN.
Looking into this further it seems to be something with Ember inspector that holds onto them.
With Ember Inspector:
const store = App.__container__.lookup('service:store');
store.unloadAll();
let fragments = store.peekAll('cell');
fragments.get('firstObject') // --> fragment
Without Ember Inspector (incognito window):
const store = App.__container__.lookup('service:store');
store.unloadAll();
let fragments = store.peekAll('cell');
fragments.get('firstObject') // --> undefined
I made a small test project using the examples of the documentation (a Person model with a Name fragment). I added this method so I can trace the number of fragments in the store in the console:
window.numOfFragments = () => {
return this.store.peekAll('name').get('length'));
};
First I push some data to the store in the application route model hook:
this.store.push({
data: {
id: 'p1',
type: 'person',
attributes: {
name: {
first: 'Keith',
last: 'Moon'
}
}
}
});
Right now numOfFragments returns 0. It also doesn't display the fragment in the Ember Inspector. I suspect a fragment is only created when altering the fragment data.
Now I create a completely new person record using store.createRecord
in an action triggered by a button. I don't have to create the name fragment explicitly since I added a default value to the Person model just as the documentation suggests.
name: fragment('name', { defaultValue:{ first:'', last:'' } })
The new fragment is visible in the Ember Inspector and numOfFragments returns 1.
Next I remove the new record using either unloadRecord
or destroy
directly on the record or unloadRecord
or destroyRecord
on the store. Whatever method I use, the result is the same. The record is indeed gone, but the fragment is still there and numOfFragments still returns 1. So even when destroying the containing record the fragment persists resulting in the same problem as @GeekSMN describes.
I tried to find a solution in the ext.js
file of this addon by adding this.store.unloadRecord(fragment)
to the willDestroy hook, but I get the same error as @abuiles describes.
Using a browser with or without the Ember Inspector doesn't seems to make a difference.