From 9c039fbb159cd92d9f1de09ffcb8f726ba4b6718 Mon Sep 17 00:00:00 2001 From: Dimitrii Rybakov Date: Sat, 7 Oct 2017 00:13:14 +0300 Subject: [PATCH 1/2] fix cyclic update --- lib/relationHooks.js | 66 ++++++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/lib/relationHooks.js b/lib/relationHooks.js index b5914bf..f3a3aaa 100644 --- a/lib/relationHooks.js +++ b/lib/relationHooks.js @@ -21,8 +21,39 @@ var setupRelationHooks = function(relatedCollection, relation) { }); }; + var getTopLevelFields = function(fields) { + return fields.map(function(field) { + if (field.indexOf('.') >= 0) { + return field.split('.')[0]; + } + + return field; + }); + }; + + var shouldUpdate = function(modifier) { + var projectionKeys = Object.keys(relation.projection), + modifiedFields; + + if (utils.isModifier(modifier)) { + modifiedFields = Object.keys(modifier).reduce(function(fields, key) { + return fields.concat( + getTopLevelFields(Object.keys(modifier[key])) + ); + }, []); + } else { + modifiedFields = getTopLevelFields(Object.keys(modifier)); + } + + return projectionKeys.some(function(key) { + return modifiedFields.indexOf(key) >= 0; + }); + }; + var beforeUpdate = function(params, callback) { - if (relation.onUpdate === 'cascade') { + params.meta.modifiedIdentifiers = []; + + if (relation.onUpdate === 'cascade' && shouldUpdate(params.modifier)) { getModifiedIdentifiers(params.condition, function(err, identifiers) { if (err) return callback(err); @@ -39,7 +70,7 @@ var setupRelationHooks = function(relatedCollection, relation) { relation.collection.on('beforeUpdateMany', beforeUpdate); var afterUpdate = function(params, callback) { - var identifiers = params.meta.modifiedIdentifiers || []; + var identifiers = params.meta.modifiedIdentifiers; if (!identifiers.length) return callback(); @@ -47,24 +78,19 @@ var setupRelationHooks = function(relatedCollection, relation) { // in cascade mode we need to update each updated identifier var funcs = identifiers.map(function(identifier) { return function(callback) { - var projectionKeys = Object.keys(relation.projection); - if (projectionKeys.length === 1 && relation.projection[relation.key]) { - callback(); - } else { - var condition = utils.createObject( - relation.paths.identifier, - identifier - ); - - var modifier = { - $set: utils.createObject( - relation.paths.modifier, - relation.embedder(identifier) - ) - }; - - relatedCollection.updateMany(condition, modifier, callback); - } + var condition = utils.createObject( + relation.paths.identifier, + identifier + ); + + var modifier = { + $set: utils.createObject( + relation.paths.modifier, + relation.embedder(identifier) + ) + }; + + relatedCollection.updateMany(condition, modifier, callback); }; }); From 2aaf164e9f639236508a3201fe723be61df83f3f Mon Sep 17 00:00:00 2001 From: Dimitrii Rybakov Date: Wed, 8 Nov 2017 18:41:19 +0300 Subject: [PATCH 2/2] refactor --- lib/relationHooks.js | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/relationHooks.js b/lib/relationHooks.js index f3a3aaa..0fcaef0 100644 --- a/lib/relationHooks.js +++ b/lib/relationHooks.js @@ -31,33 +31,41 @@ var setupRelationHooks = function(relatedCollection, relation) { }); }; - var shouldUpdate = function(modifier) { - var projectionKeys = Object.keys(relation.projection), - modifiedFields; - + var getModifiedFields = function(modifier) { if (utils.isModifier(modifier)) { - modifiedFields = Object.keys(modifier).reduce(function(fields, key) { + return Object.keys(modifier).reduce(function(fields, key) { return fields.concat( getTopLevelFields(Object.keys(modifier[key])) ); }, []); - } else { - modifiedFields = getTopLevelFields(Object.keys(modifier)); } - return projectionKeys.some(function(key) { + return getTopLevelFields(Object.keys(modifier)); + }; + + var shouldUpdate = function(modifier) { + var projectionKeys = Object.keys(relation.projection), + modifiedFields = getModifiedFields(modifier); + + return projectionKeys.filter(function(key) { + return key !== relation.key; + }).some(function(key) { return modifiedFields.indexOf(key) >= 0; }); }; var beforeUpdate = function(params, callback) { - params.meta.modifiedIdentifiers = []; + params.meta.modifiedIdentifiers = params.meta.modifiedIdentifiers || {}; - if (relation.onUpdate === 'cascade' && shouldUpdate(params.modifier)) { + if ( + relation.onUpdate === 'cascade' && + !params.meta.modifiedIdentifiers[relation.key] && + shouldUpdate(params.modifier) + ) { getModifiedIdentifiers(params.condition, function(err, identifiers) { if (err) return callback(err); - params.meta.modifiedIdentifiers = identifiers; + params.meta.modifiedIdentifiers[relation.key] = identifiers; callback(); }); @@ -70,9 +78,9 @@ var setupRelationHooks = function(relatedCollection, relation) { relation.collection.on('beforeUpdateMany', beforeUpdate); var afterUpdate = function(params, callback) { - var identifiers = params.meta.modifiedIdentifiers; + var identifiers = params.meta.modifiedIdentifiers[relation.key] || []; - if (!identifiers.length) return callback(); + if (!identifiers.length || !shouldUpdate(params.modifier)) return callback(); if (relation.onUpdate === 'cascade') { // in cascade mode we need to update each updated identifier