Skip to content

Commit

Permalink
Improving recursive deletes in AIR/general case
Browse files Browse the repository at this point in the history
  • Loading branch information
dima committed Dec 17, 2010
1 parent ec453fc commit 730bdda
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 52 deletions.
3 changes: 3 additions & 0 deletions framework/src/org/restfulx/controllers/CacheController.as
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ package org.restfulx.controllers {
import org.restfulx.utils.RxUtils;
import org.restfulx.utils.TypedArray;

import mx.utils.ObjectUtil;

/**
* In-memory model data store. This class is responsible for storing models
* that make it into memory as a result of various <code>ModelsController</code>
Expand Down Expand Up @@ -151,6 +153,7 @@ package org.restfulx.controllers {
public function destroy(model:RxModel, serviceProvider:IServiceProvider, opts:Object = null):void {
var fqn:String = getQualifiedClassName(model);
if (opts != null && opts.hasOwnProperty("recursive") && opts["recursive"] == true) {
Rx.log.debug("recursively cleaning up associations for: " + fqn + " with id: " + model["id"]);
RxUtils.cleanupModelAssociations(model, fqn);
}
RxUtils.cleanupModelReferences(model, fqn);
Expand Down
1 change: 1 addition & 0 deletions framework/src/org/restfulx/services/ServiceResponder.as
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ package org.restfulx.services {
this.onSuccess = onSuccess;
this.onFailure = onFailure;
this.unmarshallDisconnected = unmarshallDisconnected;
this.recursive = recursive;
}

public function get handler():Function {
Expand Down
122 changes: 73 additions & 49 deletions framework/src/org/restfulx/services/air/AIRServiceProvider.as
Original file line number Diff line number Diff line change
Expand Up @@ -503,31 +503,7 @@ package org.restfulx.services.air {
executeSQLStatement(sqlStatement);

if (recursive) {
var refName:String = Rx.models.state.names[fqn]["single"];
Rx.log.debug(refName);

for (var rel:String in Rx.models.state.refs[fqn]) {
var relObject:Object = Rx.models.state.refs[fqn][rel];
var relType:String = relObject["relType"];
var relObjType:String = relObject["type"];
if (relType == "HasOne" || relType == "HasMany") {
var tableName:String = Rx.models.state.controllers[relObjType]

var recursiveStatement:SQLStatement = getSQLStatement("DELETE FROM " + tableName +
"WHERE " + refName + "_id='" + object["id"] + "'");

Rx.log.debug("recursively deleting children:executing SQL:" + recursiveStatement.text);
recursiveStatement.addEventListener(SQLEvent.RESULT, function(event:SQLEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.debug("successfully deleted children");
});
recursiveStatement.addEventListener(SQLErrorEvent.ERROR, function(event:SQLErrorEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.error("failed to delete children of " + refName + ":" + object["id"] + " from the database: " + event.error);
});
executeSQLStatement(recursiveStatement);
}
}
purgeRecursively(object, fqn);
}
}

Expand Down Expand Up @@ -671,31 +647,79 @@ package org.restfulx.services.air {
executeSQLStatement(sqlStatement);

if (recursive) {
var refName:String = Rx.models.state.names[fqn]["single"];
Rx.log.debug(refName);

for (var rel:String in Rx.models.state.refs[fqn]) {
var relObject:Object = Rx.models.state.refs[fqn][rel];
var relType:String = relObject["relType"];
var relObjType:String = relObject["type"];
if (relType == "HasOne" || relType == "HasMany") {
var tableName:String = Rx.models.state.controllers[relObjType]

var recursiveStatement:SQLStatement = getSQLStatement("UPDATE " + tableName +
" SET sync=:sync WHERE " + refName + "_id='" + object["id"] + "'");
recursiveStatement.parameters[":sync"] = syncStatus;

Rx.log.debug("recursively updating children sync status:executing SQL:" + recursiveStatement.text);
recursiveStatement.addEventListener(SQLEvent.RESULT, function(event:SQLEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.debug("successfully updated children sync status");
});
recursiveStatement.addEventListener(SQLErrorEvent.ERROR, function(event:SQLErrorEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.error("failed to update sync status on children of " + refName + ":" + object["id"] + " from the database: " + event.error);
});
executeSQLStatement(recursiveStatement);
updateSyncStatusRecursively(object, fqn, syncStatus);
}
}

private function updateSyncStatusRecursively(object:Object, fqn:String, syncStatus:String):void {
var refName:String = Rx.models.state.names[fqn]["single"];
for (var rel:String in Rx.models.state.refs[fqn]) {
var relObject:Object = Rx.models.state.refs[fqn][rel];
var relType:String = relObject["relType"];
var relObjType:String = relObject["type"];
if (relType == "HasOne" || relType == "HasMany") {
var tableName:String = Rx.models.state.controllers[relObjType];

if (!RxUtils.isEmpty(relObject["referAs"])) {
refName = relObject["referAs"];
}

var recursiveStatement:SQLStatement = getSQLStatement("UPDATE " + tableName +
" SET sync=:sync WHERE " + refName + "_id='" + object["id"] + "'");
recursiveStatement.parameters[":sync"] = syncStatus;

if (relType == "HasMany") {
for each (var nestedObject:Object in object[rel]) {
updateSyncStatusRecursively(nestedObject, relObjType, syncStatus);
}
}

Rx.log.debug("executing SQL:" + recursiveStatement.text);
recursiveStatement.addEventListener(SQLEvent.RESULT, function(event:SQLEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.debug("successfully updated children sync status");
});
recursiveStatement.addEventListener(SQLErrorEvent.ERROR, function(event:SQLErrorEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.error("failed to remove/update children of: " + object["id"] + " from the database: " + event.error);
});
executeSQLStatement(recursiveStatement);
}
}
}

private function purgeRecursively(object:Object, fqn:String):void {
var refName:String = Rx.models.state.names[fqn]["single"];
for (var rel:String in Rx.models.state.refs[fqn]) {
var relObject:Object = Rx.models.state.refs[fqn][rel];
var relType:String = relObject["relType"];
var relObjType:String = relObject["type"];
if (relType == "HasOne" || relType == "HasMany") {
var tableName:String = Rx.models.state.controllers[relObjType];

if (!RxUtils.isEmpty(relObject["referAs"])) {
refName = relObject["referAs"];
}

var recursiveStatement:SQLStatement = getSQLStatement("DELETE FROM " + tableName +
"WHERE " + refName + "_id='" + object["id"] + "'");

if (relType == "HasMany") {
for each (var nestedObject:Object in object[rel]) {
purgeRecursively(nestedObject, relObjType);
}
}

Rx.log.debug("recursively deleting children:executing SQL:" + recursiveStatement.text);
recursiveStatement.addEventListener(SQLEvent.RESULT, function(event:SQLEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.debug("successfully deleted children");
});
recursiveStatement.addEventListener(SQLErrorEvent.ERROR, function(event:SQLErrorEvent):void {
event.currentTarget.removeEventListener(event.type, arguments.callee);
Rx.log.error("failed to delete children of " + refName + ":" + object["id"] + " from the database: " + event.error);
});
executeSQLStatement(recursiveStatement);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion framework/src/org/restfulx/utils/ModelsMetadata.as
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ package org.restfulx.utils {
}

refs[fqn][refName] = {type: refType, referAs: referAs, conditions: conditions, sorts: sorts, relType: relType,
polymorphic: polymorphic};
polymorphic: polymorphic, dependencies: dependencies};

for each (var dependency:String in dependencies) {
if (controllers[dependency] && dependency != fqn && (eager[fqn] as Array).indexOf(dependency) == -1) {
Expand Down
6 changes: 4 additions & 2 deletions framework/src/org/restfulx/utils/RxUtils.as
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ package org.restfulx.utils {
}

/**
* Clean up all HasOne,HasMany associations that this model refers to.
* Clean up all HasOne,HasMany associations that this model refers to recursively
*
* @param model model instance to clean-up references for
* @param fqn FullyQualifiedName of the model
Expand All @@ -224,10 +224,12 @@ package org.restfulx.utils {
var items:ModelsCollection = Rx.models.cache.data[relObjectType];
if (relType == "HasMany") {
for each (var relatedItem:Object in model[reference] as ModelsCollection) {
cleanupModelAssociations(relatedItem, relObjectType);
items.removeItem(relatedItem);
}
} else if (relType == "HasOne") {
items.removeItem(model[reference])
cleanupModelAssociations(model[reference], relObjectType);
items.removeItem(model[reference]);
}
}
}
Expand Down

0 comments on commit 730bdda

Please sign in to comment.