Skip to content

Commit

Permalink
Merge branch '0.8.x' into devel
Browse files Browse the repository at this point in the history
  • Loading branch information
emacsway committed Jan 8, 2018
2 parents e5dac18 + aac3a3a commit 4e08417
Showing 1 changed file with 28 additions and 18 deletions.
46 changes: 28 additions & 18 deletions store.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,10 @@ function namespace(root) {
return this._getTransaction().add(this, obj, function() { // onCommit
var dirty = this;
var old = this.store.getObjectAccessor().getObjectState(dirty.obj);
dirty.store.getObjectAccessor().delTmpPk(dirty.obj);
dirty.store.getObjectAccessor().delTmpPkValues(dirty.obj);
return this.store.getRemoteStore().add(dirty.obj).then(function(obj) {
return when(dirty.store._localStore.update(obj), function(obj) { // use decompose(obj, obj)
// We have to handle the whole aggregate received from the server
return when(dirty.store.decompose(obj, obj), function(obj) {
return when(dirty.store.syncDependencies(obj, old), function() {
return obj;
});
Expand All @@ -222,20 +223,17 @@ function namespace(root) {
return when(this.store._localStore.delete(this.obj));
}, function() { // onPending
var dirty = this;
this.store.getObjectAccessor().setTmpPk(dirty.obj);
return when(dirty.store._localStore.add(dirty.obj), function(obj) { // use decompose(dirty.obj)
this.store.getObjectAccessor().populateTmpPkValues(dirty.obj);
// Don't use decompose here, we use Store API to add object to aggregate
return when(dirty.store._localStore.add(dirty.obj), function(obj) {
dirty.obj = obj;
return when(obj);
});
}, function() { // onAutoCommit
var dirty = this;
return when(dirty.store.getRemoteStore().add(dirty.obj), function(obj) {
// TODO: the obj can be an aggregate? Use decompose with merging strategy?
// Aggregate is the boundary of transaction.
// Usually aggregate uses optimistic offline lock of whole aggregate
// for concurrency control.
// So, we don't have to sync aggregate here, but we have to set at least PK and default values.
return when(dirty.store._localStore.add(dirty.obj), function(obj) { // use decompose(dirty.obj)
// We have to handle the whole aggregate received from the server
return when(dirty.store.decompose(dirty.obj), function(obj) {
dirty.obj = obj;
return when(obj);
});
Expand All @@ -248,10 +246,12 @@ function namespace(root) {
return this._getTransaction().update(this, obj, old, function() {
var dirty = this;
return this.store.getRemoteStore().update(dirty.obj).then(function(obj) {
return dirty.store._localStore.update(obj); // use decompose(obj, obj)
// We have to handle the whole aggregate received from the server
return dirty.store.decompose(obj, obj);
});
}, function() {
var dirty = this;
// Don't use decompose here, we track each object of aggregate during transaction
return when(this.store._localStore.update(clone(dirty.old, dirty.obj, function(obj, attr, value) {
return dirty.store.getObjectAccessor().setValue(obj, attr, value);
})));
Expand Down Expand Up @@ -540,7 +540,8 @@ function namespace(root) {
* Load related stores from composition of object.
*/
decompose: function(record, associatedObj) {
return new Decompose(this, record, associatedObj).compute();
var obj = this.restoreObject(record);
return new Decompose(this, obj, associatedObj).compute();
},
_prepareQuery: function(queryEngine, query) {
var self = this;
Expand Down Expand Up @@ -1149,7 +1150,7 @@ function namespace(root) {
_pkValueIsDefined: function(value) {
return value !== null && typeof value !== "undefined";
},
setTmpPk: function(obj) {
populateTmpPkValues: function(obj) {
var pkValue = this.getPk(obj);
if (pkValue instanceof Array) {
for (var i = 0; i < pkValue.length; i++) {
Expand All @@ -1164,7 +1165,7 @@ function namespace(root) {
}
this.setPk(obj, pkValue);
},
delTmpPk: function(obj) {
delTmpPkValues: function(obj) {
var pk = toArray(this.pk);
for (var i = 0; i < pk.length; i++) {
var field = pk[i];
Expand Down Expand Up @@ -1577,9 +1578,9 @@ function namespace(root) {
};


function Decompose(store, record, associatedObj) {
function Decompose(store, obj, associatedObj) {
this._store = store;
this._obj = store.restoreObject(record);
this._obj = obj;
this._previousState = {};
this._associatedObj = associatedObj;
if (!this._associatedObj && this._store.getObjectAccessor().pkExists(this._obj)) {
Expand Down Expand Up @@ -1638,6 +1639,13 @@ function namespace(root) {
// When we add an aggregate to a single endpoint,
// the all child of the aggregate in the memory don't have PK,
// thus, we have to associate child manually based on their order.
//
// Aggregate is the boundary of transaction.
// Usually aggregate uses optimistic offline lock for whole aggregate (the root of aggregate)
// for concurrency control.
// So, we don't have to sync aggregate here, but we have to set at least PK and default values.
// We assume that concurrent transaction can't to delete any item of aggregate because of
// optimistic offline lock for whole aggregate (the root of aggregate).
var oldRelatedObjectList = self._previousState[relationName] || [];
if (!oldRelatedObjectList.length) {
oldRelatedObjectList = relatedStore.findList(relation.getRelatedQuery(self._obj));
Expand Down Expand Up @@ -2113,7 +2121,6 @@ function namespace(root) {
},
restoreObject: function(record) {
var obj = this._mapper.isLoaded(record) ? record : this._mapper.load(record);
this._setInitObjectState(obj);
return obj;
},
getInitObjectState: function(obj) {
Expand Down Expand Up @@ -2392,7 +2399,9 @@ function namespace(root) {
}
}));
}).then(function(obj) {
return self.restoreObject(obj);
obj = self.restoreObject(obj);
this._setInitObjectState(obj);
return obj;
});

},
Expand All @@ -2414,6 +2423,7 @@ function namespace(root) {
}).then(function(objectList) {
for (var i = 0; i < objectList.length; i++) {
objectList[i] = self.restoreObject(objectList[i]);
this._setInitObjectState(objectList[i]);
}
return objectList;
});
Expand Down

0 comments on commit 4e08417

Please sign in to comment.