Skip to content

Commit

Permalink
es6 RecordArrayManager
Browse files Browse the repository at this point in the history
  • Loading branch information
runspired committed Dec 9, 2016
1 parent c2b5fb9 commit c0f2de0
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 49 deletions.
10 changes: 9 additions & 1 deletion addon/-private/system/model/internal-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Relationships from "ember-data/-private/system/relationships/state/create
import Snapshot from "ember-data/-private/system/snapshot";
import EmptyObject from "ember-data/-private/system/empty-object";
import isEnabled from 'ember-data/-private/features';
import OrderedSet from "ember-data/-private/system/ordered-set";

import {
getOwner
Expand Down Expand Up @@ -113,7 +114,6 @@ export default class InternalModel {
this.modelName = modelClass.modelName;
this.dataHasInitialized = false;
this._loadingPromise = null;
this._recordArrays = undefined;
this._record = null;
this.currentState = RootState.empty;
this.isReloading = false;
Expand All @@ -123,6 +123,7 @@ export default class InternalModel {

// caches for lazy getters
this.__deferredTriggers = null;
this.__recordArrays = null;
this._references = null;
this._recordReference = null;
this.__inFlightAttributes = null;
Expand All @@ -142,6 +143,13 @@ export default class InternalModel {
return this._recordReference;
}

get _recordArrays() {
if (this.__recordArrays === null) {
this.__recordArrays = OrderedSet.create();
}
return this.__recordArrays;
}

get references() {
if (this._references === null) {
this._references = new EmptyObject();
Expand Down
68 changes: 36 additions & 32 deletions addon/-private/system/record-array-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
FilteredRecordArray,
AdapterPopulatedRecordArray
} from "ember-data/-private/system/record-arrays";
import OrderedSet from "ember-data/-private/system/ordered-set";

const {
get,
Expand Down Expand Up @@ -62,11 +61,13 @@ const {
@class RecordArrayManager
@namespace DS
@private
@extends Ember.Object
*/
export default Ember.Object.extend({
init() {
export default class RecordArrayManager {
constructor(options) {
heimdall.increment(create);
this.store = options.store;
this.isDestroying = false;
this.isDestroyed = false;
this.filteredRecordArrays = MapWithDefault.create({
defaultValue() { return []; }
});
Expand All @@ -77,20 +78,19 @@ export default Ember.Object.extend({

this.changedRecords = [];
this._adapterPopulatedRecordArrays = [];
},
}

recordDidChange(record) {
heimdall.increment(recordDidChange);
if (this.changedRecords.push(record) !== 1) { return; }

emberRun.schedule('actions', this, this.updateRecordArrays);
},
}

recordArraysForRecord(record) {
recordArraysForRecord(internalModel) {
heimdall.increment(recordArraysForRecord);
record._recordArrays = record._recordArrays || OrderedSet.create();
return record._recordArrays;
},
return internalModel._recordArrays;
}

/**
This method is invoked whenever data is loaded into the store by the
Expand All @@ -115,18 +115,18 @@ export default Ember.Object.extend({
});

this.changedRecords.length = 0;
},
}

_recordWasDeleted(record) {
_recordWasDeleted(internalModel) {
heimdall.increment(_recordWasDeleted);
let recordArrays = record._recordArrays;
let recordArrays = internalModel.__recordArrays;

if (!recordArrays) { return; }

recordArrays.forEach(array => array._removeInternalModels([record]));
recordArrays.forEach(array => array._removeInternalModels([internalModel]));

record._recordArrays = null;
},
internalModel.__recordArrays = null;
}

_recordWasChanged(record) {
heimdall.increment(_recordWasChanged);
Expand All @@ -137,7 +137,7 @@ export default Ember.Object.extend({
filter = get(array, 'filterFunction');
this.updateFilterRecordArray(array, filter, typeClass, record);
});
},
}

//Need to update live arrays on loading
recordWasLoaded(record) {
Expand All @@ -155,7 +155,7 @@ export default Ember.Object.extend({
let liveRecordArray = this.liveRecordArrays.get(typeClass);
this._addInternalModelToRecordArray(liveRecordArray, record);
}
},
}

/**
Update an individual filter.
Expand All @@ -176,7 +176,7 @@ export default Ember.Object.extend({
recordArrays.delete(array);
array._removeInternalModels([internalModel]);
}
},
}

_addInternalModelToRecordArray(array, internalModel) {
heimdall.increment(_addRecordToRecordArray);
Expand All @@ -185,7 +185,7 @@ export default Ember.Object.extend({
array._pushInternalModels([internalModel]);
recordArrays.add(array);
}
},
}

syncLiveRecordArray(array, modelClass) {
let hasNoPotentialDeletions = this.changedRecords.length === 0;
Expand All @@ -203,7 +203,7 @@ export default Ember.Object.extend({
}

this.populateLiveRecordArray(array, modelClass);
},
}

populateLiveRecordArray(array, modelClass) {
heimdall.increment(populateLiveRecordArray);
Expand All @@ -218,7 +218,7 @@ export default Ember.Object.extend({
this._addInternalModelToRecordArray(array, record);
}
}
},
}

/**
This method is invoked if the `filterFunction` property is
Expand All @@ -245,7 +245,7 @@ export default Ember.Object.extend({
this.updateFilterRecordArray(array, filter, modelClass, record);
}
}
},
}

/**
Get the `DS.RecordArray` for a type, which contains all loaded records of
Expand All @@ -258,7 +258,7 @@ export default Ember.Object.extend({
liveRecordArrayFor(typeClass) {
heimdall.increment(liveRecordArrayFor);
return this.liveRecordArrays.get(typeClass);
},
}

/**
Create a `DS.RecordArray` for a type.
Expand All @@ -276,7 +276,7 @@ export default Ember.Object.extend({
isLoaded: true,
manager: this
});
},
}

/**
Create a `DS.FilteredRecordArray` for a type and register it for updates.
Expand All @@ -301,7 +301,7 @@ export default Ember.Object.extend({
this.registerFilteredRecordArray(array, typeClass, filter);

return array;
},
}

/**
Create a `DS.AdapterPopulatedRecordArray` for a type with given query.
Expand All @@ -324,7 +324,7 @@ export default Ember.Object.extend({
this._adapterPopulatedRecordArrays.push(array);

return array;
},
}

/**
Register a RecordArray for a given type to be backed by
Expand All @@ -343,7 +343,7 @@ export default Ember.Object.extend({
recordArrays.push(array);

this.updateFilter(array, typeClass, filter);
},
}

/**
Unregister a RecordArray.
Expand Down Expand Up @@ -374,16 +374,20 @@ export default Ember.Object.extend({
}
}
}
},
}

willDestroy() {
this._super(...arguments);

this.filteredRecordArrays.forEach(value => flatten(value).forEach(destroy));
this.liveRecordArrays.forEach(destroy);
this._adapterPopulatedRecordArrays.forEach(destroy);
this.isDestroyed = true;
}
});

destroy() {
this.isDestroying = true;
Ember.run.schedule('actions', this, this.willDestroy);
}
}

function destroy(entry) {
entry.destroy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ export default RecordArray.extend({
links: cloneNull(payload.links)
});

internalModels.forEach(record => this.manager.recordArraysForRecord(record).add(this));
for (let i = 0, l = internalModels.length; i < l; i++) {
let internalModel = internalModels[i];
this.manager.recordArraysForRecord(internalModel).add(this)
}

// TODO: should triggering didLoad event be the last action of the runLoop?
Ember.run.once(this, 'trigger', 'didLoad');
Expand Down
4 changes: 2 additions & 2 deletions addon/-private/system/record-arrays/record-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export default Ember.ArrayProxy.extend(Ember.Evented, {

_dissociateFromOwnRecords() {
this.get('content').forEach(internalModel => {
let recordArrays = internalModel._recordArrays;
let recordArrays = internalModel.__recordArrays;

if (recordArrays) {
recordArrays.delete(this);
Expand All @@ -215,7 +215,7 @@ export default Ember.ArrayProxy.extend(Ember.Evented, {
@private
*/
_unregisterFromManager() {
get(this, 'manager').unregisterRecordArray(this);
this.manager.unregisterRecordArray(this);
},

willDestroy() {
Expand Down
4 changes: 1 addition & 3 deletions addon/-private/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,9 +214,7 @@ Store = Service.extend({
this._backburner = new Backburner(['normalizeRelationships', 'syncRelationships', 'finished']);
// internal bookkeeping; not observable
this.typeMaps = {};
this.recordArrayManager = RecordArrayManager.create({
store: this
});
this.recordArrayManager = new RecordArrayManager({ store: this });
this._pendingSave = [];
this._instanceCache = new ContainerInstanceCache(getOwner(this), this);

Expand Down
2 changes: 2 additions & 0 deletions tests/dummy/app/routes/query/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default Route.extend({
let modelName = params.modelName;
delete params.modelName;

console.time('ember-data');
let token = heimdall.start('ember-data');
return this.get('store').query(modelName, params)
.then((records) => {
Expand All @@ -33,6 +34,7 @@ export default Route.extend({
// and clutter our benchmarks and make it harder to time.
records.toArray();
heimdall.stop(token);
console.timeEnd('ember-data');
window.result = heimdall.toString();

return records;
Expand Down
31 changes: 21 additions & 10 deletions tests/unit/record-arrays/record-array-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test('custom initial state', function(assert) {
isUpdating: true,
content,
store
})
});
assert.equal(get(recordArray, 'isLoaded'), true);
assert.equal(get(recordArray, 'isUpdating'), false); // cannot set as default value:
assert.equal(get(recordArray, 'type'), 'apple');
Expand Down Expand Up @@ -192,14 +192,25 @@ test('#_removeInternalModels', function(assert) {
assert.deepEqual(content, [], 'now contains no models');
});

class FakeInternalModel {
constructor(record) {
this._record = record;
this.__recordArrays = null;
}

get _recordArrays() {
return this.__recordArrays;
}

getRecord() { return this._record; }

createSnapshot() {
return this._record;
}
}

function internalModelFor(record) {
return {
_recordArrays: undefined,
getRecord() { return record; },
createSnapshot() {
return record;
}
};
return new FakeInternalModel(record);
}

test('#save', function(assert) {
Expand Down Expand Up @@ -237,7 +248,7 @@ test('#destroy', function(assert) {
let internalModel1 = internalModelFor(model1);

// TODO: this will be removed once we fix ownership related memory leaks.
internalModel1._recordArrays = {
internalModel1.__recordArrays = {
delete(array) {
didDissociatieFromOwnRecords++;
assert.equal(array, recordArray);
Expand Down Expand Up @@ -308,7 +319,7 @@ test('#destroy', function(assert) {
let internalModel1 = internalModelFor(model1);

// TODO: this will be removed once we fix ownership related memory leaks.
internalModel1._recordArrays = {
internalModel1.__recordArrays = {
delete(array) {
didDissociatieFromOwnRecords++;
assert.equal(array, recordArray);
Expand Down

0 comments on commit c0f2de0

Please sign in to comment.