Error "rules is cyclic or exceeds maximum cascading level"

290
7
03-07-2024 06:32 AM
FlorianArtelt1
New Contributor II

We are using an atrribute rules in ArcGIS Pro 3.1.4.. We want to update a number of features in the feature layer on which the rule is located. We am trying to create an attribute rule that updates the "Pushvalue"-field across all features in the same layer that share the same "GemeindeID".

We have seen the following solution approach, that describes how we prevent running into an infinite loop.
We do not see how we can escape the infinite loop in this example.

Solved: The Evaluation of attribute rule is cyclic or exce... - Esri Community

But we are still getting the cascade error message: "rules is cyclic or exceeds maximum cascading level". And we think that this is justified since the changes in the individual lines triggers the attribute rule over and over again. @IlkaPleiser1 @JohannesLindner  @HusseinNasser2 

 

// calculed Field $feature.Helper
// Triggers: Insert, Update
// Exclude from application evaluation


var GID = $feature.GemeindeID
var GLID = $feature.GlobalID


// filter current featureset except the feature that is edited rn
var SQL = "GemeindeID = @GID AND GlobalID <> @GLID"
var sirenen = FeatureSetByName($datastore, "Sirenen", ["*"])
var filterSirene = filter($featureset, SQL)
console(count(filterSirene))

var updates = []
for(var f in filterSirene) {
    if(f.GlobalID == $feature.GlobalID) { continue }
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            Pushvalue: $feature.Pushvalue
            }
        }
    Push(updates, u)
}

return {
    result: {
        attributes: {
            Pushvalue: $feature.Pushvalue}
        },
    edit: [{
        className: "Sirenen",
        updates: updates
        }]
}

 

 

 

Tags (2)
0 Kudos
7 Replies
HusseinNasser2
Esri Contributor

Yeah your rule will trigger forever, just like in recursion you will need a base condition for your attribute rule. 

 

And that is if pushvalue is the same, just no-op.

 

// calculed Field $feature.Helper
// Triggers: Insert, Update
// Exclude from application evaluation

//add base condition 
if($originalFeature.pushvalue == $feature.pushvalue) return;

var GID = $feature.GemeindeID
var GLID = $feature.GlobalID


// filter current featureset except the feature that is edited rn
var SQL = "GemeindeID = @GID AND GlobalID <> @GLID"
var sirenen = FeatureSetByName($datastore, "Sirenen", ["*"])
var filterSirene = filter($featureset, SQL)
console(count(filterSirene))

var updates = []
for(var f in filterSirene) {
    if(f.GlobalID == $feature.GlobalID) { continue }
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            Pushvalue: $feature.Pushvalue
            }
        }
    Push(updates, u)
}

return {
    result: {
        attributes: {
            Pushvalue: $feature.Pushvalue}
        },
    edit: [{
        className: "Sirenen",
        updates: updates
        }]
}

 

 

also for additional optimization (although you might have done on purpose for Editor tracking), add a filter to your sql to only push the different  

var pushValue = $feature.pushvalue

var SQL = "GemeindeID = @GID AND GlobalID <> @GLID AND pushvalue <> @pushValue"

 

0 Kudos
FlorianArtelt1
New Contributor II

Thanks for your fast reply.

When using the provided syntax, we are still getting the cascade error message. We have deployed the syntax in three different projects with three different datasets and get the same error message. Nevertheless the recommended base condition seems to be logical and plausible.

We received the following dictionary for the "updates"-variable in line 18 after looping through the features. 

[{"attributes":{"Pushvalue":null},"globalID":"{CA126DB3-A2FB-4421-A3A9-6DE3A91444A1}"},{"attributes":{"Pushvalue":null},"globalID":"{2A6CD837-5D17-4BFF-93C3-90433747E44E}"},{"attributes":{"Pushvalue":null},"globalID":"{82CCCC1C-BBA0-4462-BE59-B2302073AC7D}"}]

This seems to be valid.

Do you have any idea what's causing the issue?

Here you can see the sample attribute table. We just want to push the inserted value from the Pushvalue-Field to all features with that shares the same "GemeindeID".

FlorianArtelt1_0-1709891792160.png

Thanks in advance.

0 Kudos
HusseinNasser2
Esri Contributor

Ok I forgot to deal with one more thing which is when the value is the same don't even attempt the update.

 

Tested this one locally and it worked. 

 

// calculed Field $feature.Helper
// Triggers: Insert, Update
// Exclude from application evaluation

//add base condition 
if($originalFeature.pushvalue == $feature.pushvalue) return;

var GID = $feature.GemeindeID
var GLID = $feature.GlobalID


// filter current featureset except the feature that is edited rn
var SQL = "GemeindeID = @GID AND GlobalID <> @GLID"
var sirenen = FeatureSetByName($datastore, "Sirenen", ["*"])
var filterSirene = filter($featureset, SQL)
console(count(filterSirene))

var updates = []
for(var f in filterSirene) {
    if(f.GlobalID == $feature.GlobalID) continue;
    //don't update values that are the same to avoid recursion.
    if(f.pushvalue == $feature.pushvalue) continue;
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            Pushvalue: $feature.Pushvalue
            }
        }
    Push(updates, u)
}

return {
    result: {
        attributes: {
            Pushvalue: $feature.Pushvalue}
        },
    edit: [{
        className: "Sirenen",
        updates: updates
        }]
}

 

 

HusseinNasser2
Esri Contributor

This one is really interesting, just found another issue when you have more than 6 features to update, because we have a limit of the number of Arcade engines the script hit that limit pretty soon.  

 

The only workaround to really fix this is to have an additional field, I added a field called isPush with a integer value. We want to essentially differentiate between a user update changing the pushvalue vs an automated attribute rule update. 

You can hide the ispush field from users as it will only be used by the attribute rule.

 

if ($feature.ispush == 1) return {"result": {"attributes": {"ispush": 0}}};

 

Final script.. 

 

// calculed Field $feature.Helper
// Triggers: Insert, Update
// Exclude from application evaluation

//add base condition 
if ($feature.ispush == 1) return {"result": {"attributes": {"ispush": 0}}};

if($originalFeature.pushvalue == $feature.pushvalue) return;

var GID = $feature.GemeindeID
var GLID = $feature.GlobalID


// filter current featureset except the feature that is edited rn
var SQL = "GemeindeID = @GID AND GlobalID <> @GLID"
var sirenen = FeatureSetByName($datastore, "Sirenen", ["*"])
var filterSirene = filter($featureset, SQL)
console(count(filterSirene))

var updates = []
for(var f in filterSirene) {
    if(f.GlobalID == $feature.GlobalID) continue;
    //don't update values that are the same to avoid recursion.
    if(f.pushvalue == $feature.pushvalue) continue;
    var u  = {
        globalID: f.GlobalID,
        attributes: {
            Pushvalue: $feature.Pushvalue,
            ispush :1
            }
        }
    Push(updates, u)
}

return {
    result: {
        attributes: {
            Pushvalue: $feature.Pushvalue}
        },
    edit: [{
        className: "Sirenen",
        updates: updates
        }]
}

 

 

FlorianArtelt1
New Contributor II

Thank you very much for your help.
When I use your code and then change a value, I no longer get an error, but no change happens to features with the same "communityID" neither.

However, as soon as I re-save the rule, I get the desired behavior and all values with the same "communityID" are adjusted. But nothing happens when I adjust a value by editing it manually.

I also don't quite understand what line 24 does in your script. Wouldn't it always break out of the loop here, since $featureValue is never equal to the other values when I make a change? Therefore my var updates dictionary remains empty? But if I change the operator to !=, the other values are not changed either.

FYI I work for the German distributor of Esri. Would it be possible if we could receive your test project or send you ours?

This is how my shema looks like with the new field "is push".

FlorianArtelt1_0-1710150958900.png

Screenshot: The desired behavior after saving the whole rule instead of edit individual features.

 

0 Kudos
HusseinNasser2
Esri Contributor

I think this might be a refresh issue in the table view, closing and reopening the table should refresh it (i'll make sure to log a bug to fix that) , but if you edit the map directly you can see the value changes instantly, I had this project with labeling and symbology on.. 

but here is a video along side the data.. works as expected

 

FlorianArtelt1
New Contributor II

Thank you so much for your help! You are completely right.

It is sufficient to refresh the table view in the bottom right corner. When you are using labels, you can see the changes directly in the map! It works as desired now.

0 Kudos