Error "rules is cyclic or exceeds maximum cascading level"

203
5
Jump to solution
11-15-2022 05:26 AM
Zoggo
by
New Contributor III

I'm using a Attribute Calculation  Rule in ArcGIS Pro 3.0.2. It's a line featureclass in a fgdb. I checked "Exclude from application evaluation and triggered Insert und Update. The following very simple code is working when I alter the geometry:

var feature_ = $feature; 
return {
    "edit": [{
        "className": "HydroEdgePro",
        "updates": [{
            "objectID": feature_["OBJECTID"],
            "attributes": {
                "BEMERKUNG": "test 2"
            }
        }]
    }, {
        "className": "arcade_log",
        "adds": [{
            "attributes": {
                "Value": "test"
            }
        }]
    }]
}

  

If I try to do something with the $FeatureSet (see example below) then I always get the Error "The evaluation of attribute rules is cyclic or exceeds maximum cascading level.":

var feature_ = $feature;

var features = $FeatureSet;
var test = Count(features); 

return {
    "edit": [{
        "className": "HydroEdgePro",
        "updates": [{
            "objectID": feature_["OBJECTID"],
            "attributes": {
                "BEMERKUNG": "test 2"
            }
        }]
    }, {
        "className": "arcade_log",
        "adds": [{
            "attributes": {
                "Value": "test"
            }
        }]
    }]
}

Zoggo_0-1668518768943.png

I don't understand why this happens. During debug mode the code is working.

 

0 Kudos
1 Solution

Accepted Solutions
HusseinNasser2
Esri Contributor

When you create a feature in the geodatabase it goes into a memory buffer for performance reasons. Additional updates to the feature by its object id will go to the buffer and then finally flushed at one swoop to the database. 

This is what happened in your first rule, you created the feature, then asked AR to update the same feature field BEMERKUNG to "Test 2". The AR found that the feature is still in memory and updated the field in memory then flushed it to the database. So the database only saw one insert. 

 

However we can't always do this optimization. This optimization is not performed when a query against the class happens, because the query must see the feature being created (basic database semantics), so when a query happens to the class (that is your second rule where you did a count of the class), we had to flush the inserted feature to the database. Then the AR says wait a minute, we need to update the same feature (that is your return dictionary with objectId), that update actually becomes a physical second update which triggers the attribute rule again, and we go into the infinite cycle. 

 

So as a better practice, the attribute rule need to be written in a predictable way, if you want to updates fields in the same feature use the return "result" dictionary, with this we have knowledge in the AR to update the same row.  

Hope that clarifies it. 

View solution in original post

0 Kudos
5 Replies
HusseinNasser2
Esri Contributor

It seems that the feature triggers a rule that updates itself that triggers, which then retriggers the same attribute rule leading to an infinite loop and thus this error. 

If you want to update attributes in the same feature you can use the result keyword instead of updates.

 

 

return {
    "result": {
        "attributes": {
                "BEMERKUNG": "test 2" //this update goes to the $feature
            }
     },
    "edit": [ {
        "className": "arcade_log",
        "adds": [{
            "attributes": {
                "Value": "test"
            }
        }]
    }]
}

 

 

0 Kudos
Zoggo
by
New Contributor III

No, it's not the point. I can return the result without do the Count(Features) before. My first example is working but the second example is not. So it's not a problem of the returning object.

0 Kudos
HusseinNasser2
Esri Contributor

When you create a feature in the geodatabase it goes into a memory buffer for performance reasons. Additional updates to the feature by its object id will go to the buffer and then finally flushed at one swoop to the database. 

This is what happened in your first rule, you created the feature, then asked AR to update the same feature field BEMERKUNG to "Test 2". The AR found that the feature is still in memory and updated the field in memory then flushed it to the database. So the database only saw one insert. 

 

However we can't always do this optimization. This optimization is not performed when a query against the class happens, because the query must see the feature being created (basic database semantics), so when a query happens to the class (that is your second rule where you did a count of the class), we had to flush the inserted feature to the database. Then the AR says wait a minute, we need to update the same feature (that is your return dictionary with objectId), that update actually becomes a physical second update which triggers the attribute rule again, and we go into the infinite cycle. 

 

So as a better practice, the attribute rule need to be written in a predictable way, if you want to updates fields in the same feature use the return "result" dictionary, with this we have knowledge in the AR to update the same row.  

Hope that clarifies it. 

0 Kudos
Zoggo
by
New Contributor III

Thanks for your explanation. So it's not possible to write in another feature from the same datasource as the $feature like this?

var dangleDistance = 1000;
var feature_ = $feature;

var features = $FeatureSet;
var test = Count(features);
console(test)   
   


return {
    "result" : {
            "attributes": {
                "BEMERKUNG": "test 23"
            }
    },
    "edit": [{
                "className": "HydroEdgePro",
                "updates": [{
                    "objectID": 3833,
                    "attributes": {
                           "BEMERKUNG" : "Bem 3833"
                     }
                }]
            },{
        "className": "arcade_log",
        "adds": [{
            "attributes": {
                "Value": "test"
            }
        }]
    }]
}

 

Where "HydroEdge" is the same FeatureClass as $Feature.

 

0 Kudos
HusseinNasser2
Esri Contributor

 You need to have an exit condition, Attribute rules in this case is no different than recursive function. 

 

If you are updating object 3833, with value "Bem 3833", you might want to do a check first before doing the update. If the value is good exit the script else continue 

 

 

var dangleDistance = 1000;
var feature_ = $feature;
//query objectid 3833
var fs1 = Filter($featureset, "objectid = 3833 AND BEMERKUNG = 'Bem 3833'");
var f = First(fs1);
//if is null, means feature 3833 doesn't have the value Bem 3833.. contiue to update. 
//if is NOT null, it means the value already there, just exist
if (f != null) 
    return; //quit the script

//else update the feature
return {
    "result" : {
            "attributes": {
                "BEMERKUNG": "test 23"
            }
    },
    "edit": [{
                "className": "HydroEdgePro",
                "updates": [{
                    "objectID": 3833,
                    "attributes": {
                           "BEMERKUNG" : "Bem 3833"
                     }
                }]
            },{
        "className": "arcade_log",
        "adds": [{
            "attributes": {
                "Value": "test"
            }
        }]
    }]
}
0 Kudos