Skip to content

Commit

Permalink
simplify backburner
Browse files Browse the repository at this point in the history
  • Loading branch information
runspired committed Dec 21, 2016
1 parent 7f4c840 commit dcdc1f1
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 47 deletions.
30 changes: 12 additions & 18 deletions addon/-private/system/model/internal-model.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export default class InternalModel {
this._isDestroyed = false;
this.isError = false;
this.error = null;
this._isUpdatingRecordArrays = false;

// caches for lazy getters
this._modelClass = null;
Expand Down Expand Up @@ -366,17 +367,19 @@ export default class InternalModel {

setupData(data) {
heimdall.increment(setupData);
let token = heimdall.start('setupData');
let changedKeys = this._changedKeys(data.attributes);
assign(this._data, data.attributes);
this.pushedData();
if (this.hasRecord) {
this.record._notifyProperties(changedKeys);
}
this.didInitializeData();
heimdall.stop(token);
}

becameReady() {
emberRun.schedule('actions', this.store.recordArrayManager, this.store.recordArrayManager.recordWasLoaded, this);
this.store.recordArrayManager.recordWasLoaded(this);
}

didInitializeData() {
Expand Down Expand Up @@ -521,7 +524,7 @@ export default class InternalModel {
*/
adapterDidDirty() {
this.send('becomeDirty');
this.updateRecordArraysLater();
this.updateRecordArrays();
}

/*
Expand Down Expand Up @@ -654,7 +657,7 @@ export default class InternalModel {
setups[i].setup(this);
}

this.updateRecordArraysLater();
this.updateRecordArrays();
}

_unhandledEvent(state, name, context) {
Expand All @@ -673,7 +676,8 @@ export default class InternalModel {
if (this._deferredTriggers.push(args) !== 1) {
return;
}
emberRun.schedule('actions', this, this._triggerDeferredTriggers);

this.store._updateInternalModel(this);
}

_triggerDeferredTriggers() {
Expand Down Expand Up @@ -784,8 +788,9 @@ export default class InternalModel {
@private
*/
updateRecordArrays() {
this._updatingRecordArraysLater = false;
this.store._dataWasUpdated(this);
if (this._isUpdatingRecordArrays) { return; }
this._isUpdatingRecordArrays = true;
this.store.recordArrayManager.recordDidChange(this);
}

setId(id) {
Expand Down Expand Up @@ -843,24 +848,13 @@ export default class InternalModel {
this._inFlightAttributes = new EmptyObject();

this.send('didCommit');
this.updateRecordArraysLater();
this.updateRecordArrays();

if (!data) { return; }

this.record._notifyProperties(changedKeys);
}

/*
@method updateRecordArraysLater
@private
*/
updateRecordArraysLater() {
// quick hack (something like this could be pushed into run.once
if (this._updatingRecordArraysLater) { return; }
this._updatingRecordArraysLater = true;
emberRun.schedule('actions', this, this.updateRecordArrays);
}

addErrorMessageToAttribute(attribute, message) {
get(this.getRecord(), 'errors')._add(attribute, message);
}
Expand Down
2 changes: 1 addition & 1 deletion addon/-private/system/model/states.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function didSetProperty(internalModel, context) {
internalModel.send('becomeDirty');
}

internalModel.updateRecordArraysLater();
internalModel.updateRecordArrays();
}

// Implementation notes:
Expand Down
56 changes: 40 additions & 16 deletions addon/-private/system/record-array-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const {
_addRecordToRecordArray,
_recordWasChanged,
_recordWasDeleted,
_flushLoadedRecords,
array_flatten,
array_remove,
create,
Expand All @@ -41,6 +42,7 @@ const {
'_addInternalModelToRecordArray',
'_recordWasChanged',
'_recordWasDeleted',
'_flushLoadedRecords',
'array_fatten',
'array_remove',
'create',
Expand Down Expand Up @@ -80,12 +82,13 @@ export default Ember.Object.extend({
});

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

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

emberRun.schedule('actions', this, this.updateRecordArrays);
},
Expand All @@ -108,17 +111,22 @@ export default Ember.Object.extend({
*/
updateRecordArrays() {
heimdall.increment(updateRecordArrays);
this.changedRecords.forEach(internalModel => {
let updated = this.changedRecords;

for (let i = 0, l = updated.length; i < l; i++) {
let internalModel = updated[i];

if (internalModel.isDestroyed ||
internalModel.currentState.stateName === 'root.deleted.saved') {
internalModel.currentState.stateName === 'root.deleted.saved') {
this._recordWasDeleted(internalModel);
} else {
this._recordWasChanged(internalModel);
}
});

this.changedRecords.length = 0;
internalModel._isUpdatingRecordArrays = false;
}

updated.length = 0;
},

_recordWasDeleted(internalModel) {
Expand Down Expand Up @@ -146,19 +154,35 @@ export default Ember.Object.extend({
//Need to update live arrays on loading
recordWasLoaded(internalModel) {
heimdall.increment(recordWasLoaded);
let modelName = internalModel.modelName;
let recordArrays = this.filteredRecordArrays.get(modelName);
let filter;
if (this.loadedRecords.push(internalModel) !== 1) { return; }

recordArrays.forEach(array => {
filter = get(array, 'filterFunction');
this.updateFilterRecordArray(array, filter, modelName, internalModel);
});
emberRun.schedule('actions', this, this._flushLoadedRecords);
},

_flushLoadedRecords() {
heimdall.increment(_flushLoadedRecords);
let internalModels = this.loadedRecords;

for (let i = 0, l = internalModels.length; i < l; i++) {
let internalModel = internalModels[i];
let modelName = internalModel.modelName;

let recordArrays = this.filteredRecordArrays.get(modelName);
let filter;

if (this.liveRecordArrays.has(modelName)) {
let liveRecordArray = this.liveRecordArrays.get(modelName);
this._addInternalModelToRecordArray(liveRecordArray, internalModel);
for (let j = 0, rL = recordArrays.length; j < rL; j++) {
let array = recordArrays[j];
filter = get(array, 'filterFunction');
this.updateFilterRecordArray(array, filter, modelName, internalModel);
}

if (this.liveRecordArrays.has(modelName)) {
let liveRecordArray = this.liveRecordArrays.get(modelName);
this._addInternalModelToRecordArray(liveRecordArray, internalModel);
}
}

this.loadedRecords.length = 0;
},

/**
Expand Down
4 changes: 2 additions & 2 deletions addon/-private/system/relationships/state/relationship.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export default class Relationship {
}
record._implicitRelationships[this.inverseKeyForImplicit].addRecord(this.record);
}
this.record.updateRecordArraysLater();
this.record.updateRecordArrays();
}
this.setHasData(true);
}
Expand Down Expand Up @@ -257,7 +257,7 @@ export default class Relationship {
return;
}
this.willSync = true;
this.store._backburner.join(() => this.store._backburner.schedule('syncRelationships', this, this.flushCanonical));
this.store._updateRelationshipState(this);
}

updateLink(link) {
Expand Down
62 changes: 52 additions & 10 deletions addon/-private/system/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,13 @@ Store = Service.extend({
*/
// used for coalescing record save requests
this._pendingSave = [];
// used for coalescing relationship updates
this._updatedRelationships = [];
// used for coalescing relationship setup needs
this._pushedInternalModels = [];
// stores a reference to the flush for relationship setup
this._relationshipFlush = null;
// used for coalescing internal model updates
this._updatedInternalModels = [];

// used to keep track of all the find requests that need to be coalesced
this._pendingFetch = MapWithDefault.create({ defaultValue() { return []; } });

Expand Down Expand Up @@ -1805,6 +1808,7 @@ Store = Service.extend({
@param {InternalModel} internalModel
*/
_dataWasUpdated(internalModel) {
throw new Error('dont');
this.recordArrayManager.recordDidChange(internalModel);
},

Expand Down Expand Up @@ -2002,7 +2006,6 @@ Store = Service.extend({
heimdall.increment(_load);
let internalModel = this._internalModelForId(data.type, data.id);

// TODO @runspired move this out of here
internalModel.setupData(data);

this.recordArrayManager.recordDidChange(internalModel);
Expand Down Expand Up @@ -2368,17 +2371,17 @@ Store = Service.extend({
},

_setupRelationshipsForModel(internalModel, data) {
this._pushedInternalModels.push(internalModel, data);
if (this._relationshipFlush === null) {
this._relationshipFlush = this._backburner.schedule('normalizeRelationships', this, this._setupRelationships);
if (this._pushedInternalModels.push(internalModel, data) !== 2) {
return;
}

this._backburner.schedule('normalizeRelationships', this, this._setupRelationships);
},

_setupRelationships() {
heimdall.increment(_setupRelationships);
let setupToken = heimdall.start('store._setupRelationships');
let pushed = this._pushedInternalModels;
this._pushedInternalModels = [];
this._relationshipFlush = null;

for (let i = 0, l = pushed.length; i < l; i += 2) {
// This will convert relationships specified as IDs into DS.Model instances
Expand All @@ -2388,6 +2391,9 @@ Store = Service.extend({
let data = pushed[i + 1];
setupRelationships(this, internalModel, data);
}

pushed.length = 0;
heimdall.stop(setupToken);
},

/**
Expand Down Expand Up @@ -2632,14 +2638,50 @@ Store = Service.extend({
willDestroy() {
this._super(...arguments);
this._pushedInternalModels = null;
this._backburner.cancel(this._relationshipFlush);
this._relationshipFlush = null;
this.recordArrayManager.destroy();
this._instanceCache.destroy();

this.unloadAll();
},

_updateRelationshipState(relationship) {
if (this._updatedRelationships.push(relationship) !== 1) {
return;
}

this._backburner.join(() => {
this._backburner.schedule('syncRelationships', this, this._flushUpdatedRelationships);
});
},

_flushUpdatedRelationships() {
let updated = this._updatedRelationships;

for (let i = 0, l = updated.length; i < l; i++) {
updated[i].flushCanonical();
}

updated.length = 0;
},

_updateInternalModel(internalModel) {
if (this._updatedInternalModels.push(internalModel) !== 1) {
return;
}

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

_flushUpdatedInternalModels() {
let updated = this._updatedInternalModels;

for (let i = 0, l = updated.length; i < l; i++) {
updated[i]._triggerDeferredTriggers();
}

updated.length = 0;
},

_pushResourceIdentifier(relationship, resourceIdentifier) {
if (isNone(resourceIdentifier)) {
return;
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,8 @@ export default Route.extend({
let modelName = params.modelName;
delete params.modelName;

heimdall.enableTimelineFeatures();

let token = heimdall.start('ember-data');
return this.get('store').query(modelName, params)
.then((records) => {
Expand Down

0 comments on commit dcdc1f1

Please sign in to comment.