From 7cd5140bc1a5354cde2b85491eb16a5f848cb7af Mon Sep 17 00:00:00 2001 From: Chris Thoburn Date: Wed, 21 Dec 2016 01:48:12 -0800 Subject: [PATCH] simplify backburner --- addon/-private/system/model/internal-model.js | 26 +++------ addon/-private/system/model/states.js | 2 +- addon/-private/system/record-array-manager.js | 56 +++++++++++++------ .../relationships/state/relationship.js | 4 +- addon/-private/system/store.js | 24 ++++++++ 5 files changed, 76 insertions(+), 36 deletions(-) diff --git a/addon/-private/system/model/internal-model.js b/addon/-private/system/model/internal-model.js index 8e861cc5673..75833437c16 100644 --- a/addon/-private/system/model/internal-model.js +++ b/addon/-private/system/model/internal-model.js @@ -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; @@ -376,7 +377,7 @@ export default class InternalModel { } becameReady() { - emberRun.schedule('actions', this.store.recordArrayManager, this.store.recordArrayManager.recordWasLoaded, this); + this.store.recordArrayManager.recordWasLoaded(this); } didInitializeData() { @@ -521,7 +522,7 @@ export default class InternalModel { */ adapterDidDirty() { this.send('becomeDirty'); - this.updateRecordArraysLater(); + this.updateRecordArrays(); } /* @@ -654,7 +655,7 @@ export default class InternalModel { setups[i].setup(this); } - this.updateRecordArraysLater(); + this.updateRecordArrays(); } _unhandledEvent(state, name, context) { @@ -673,6 +674,7 @@ export default class InternalModel { if (this._deferredTriggers.push(args) !== 1) { return; } + emberRun.schedule('actions', this, this._triggerDeferredTriggers); } @@ -784,8 +786,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) { @@ -843,24 +846,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); } diff --git a/addon/-private/system/model/states.js b/addon/-private/system/model/states.js index aebb9851384..ae542b53897 100644 --- a/addon/-private/system/model/states.js +++ b/addon/-private/system/model/states.js @@ -180,7 +180,7 @@ function didSetProperty(internalModel, context) { internalModel.send('becomeDirty'); } - internalModel.updateRecordArraysLater(); + internalModel.updateRecordArrays(); } // Implementation notes: diff --git a/addon/-private/system/record-array-manager.js b/addon/-private/system/record-array-manager.js index 15259223d41..b80759d7993 100644 --- a/addon/-private/system/record-array-manager.js +++ b/addon/-private/system/record-array-manager.js @@ -21,6 +21,7 @@ const { _addRecordToRecordArray, _recordWasChanged, _recordWasDeleted, + _flushLoadedRecords, array_flatten, array_remove, create, @@ -41,6 +42,7 @@ const { '_addInternalModelToRecordArray', '_recordWasChanged', '_recordWasDeleted', + '_flushLoadedRecords', 'array_fatten', 'array_remove', 'create', @@ -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); }, @@ -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) { @@ -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; }, /** diff --git a/addon/-private/system/relationships/state/relationship.js b/addon/-private/system/relationships/state/relationship.js index e361526bc9d..75e651359d6 100644 --- a/addon/-private/system/relationships/state/relationship.js +++ b/addon/-private/system/relationships/state/relationship.js @@ -183,7 +183,7 @@ export default class Relationship { } record._implicitRelationships[this.inverseKeyForImplicit].addRecord(this.record); } - this.record.updateRecordArraysLater(); + this.record.updateRecordArrays(); } this.setHasData(true); } @@ -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) { diff --git a/addon/-private/system/store.js b/addon/-private/system/store.js index 8e2852c54ff..5e2c86347a1 100644 --- a/addon/-private/system/store.js +++ b/addon/-private/system/store.js @@ -226,6 +226,8 @@ 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 @@ -2376,6 +2378,7 @@ Store = Service.extend({ _setupRelationships() { heimdall.increment(_setupRelationships); + let setupToken = heimdall.start('store._setupRelationships'); let pushed = this._pushedInternalModels; this._pushedInternalModels = []; this._relationshipFlush = null; @@ -2388,6 +2391,7 @@ Store = Service.extend({ let data = pushed[i + 1]; setupRelationships(this, internalModel, data); } + heimdall.stop(setupToken); }, /** @@ -2640,6 +2644,26 @@ Store = Service.extend({ 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; + }, + _pushResourceIdentifier(relationship, resourceIdentifier) { if (isNone(resourceIdentifier)) { return;