Macro timing out

Alistair DeJonge asked on January 17, 2019 08:01

I have a transformation that includes some variables, a for loop, and some HTML and ultimately applies a transformation to children of a folder like this:

Documents[accordion].Children.ClassNames("customProducts_Literature.Literature_Products").WithAllData.ApplyTransformation("customProducts_Literature.Literature_Products.grid_literaturecentre"

This transformation works just fine in our staging environment, but in our production environment, the EXACT same transformation is cause event log errors like the following:

Error while evaluating expression: if(CurrentDocument.GetValue("Show_LiteratureCentre") && CurrentDocument.GetValue("ShowTopContent")){ print(ResolveMacros("\n {% if(CurrentDocument.GetValue(\"Accordion1_TopSec\") != null){ %\}\n \n {% for(i = 1; i <= CurrentDocument.GetValue(\"Number_of_Accordions_TopSec\"); i++){ %\}\n <!--\n {% accordion = CurrentDocument.GetValue(\"Accordion\" + i + \"_TopSec\"); %\}\n -->\n {% if(accordion != null){ %\}\n <!--\n {% accordionName = Documents[accordion].DisplayName; %\}\n -->\n \n {% accordionName %\}\n \n {%if(CurrentDocument.GetValue(\"Accordion\" + i + \"_Text_TopSec\",null) != null){CurrentDocument.GetValue(\"Accordion\" + i + \"_Text_TopSec\",null)}%\}\n \n {% Documents[accordion].Children.ClassNames(\"customProducts_Literature.Literature_Products\").WithAllData.ApplyTransformation(\"customProducts_Literature.Literature_Products.grid_literaturecentre\") #%\}\n \n {% if(DocumentCulture == \"en-us\"){ %\}\n {% GetResourceString(\"custom.lblPlaceOrder\", DocumentCulture) %\}\n {% } %\}\n \n \n {% } %\}\n {% } %\}\n \n {% } %\}\n")) } |(user)alistair|(hash)b4b1e17afefcaa9f79180a29cea7d53923c4c4ccd2578a9f1d08011e83239a25

CMS.MacroEngine.EvaluationTimeoutException: Evaluation timeout in the expression ' if(CurrentDocument.GetValue("Show_LiteratureCentre") && CurrentDocument.GetValue("ShowTopContent")){ print(ResolveMacros("\n {% if(CurrentDocument.GetValue(\"Accordion1_TopSec\") != null){ %\}\n \n {% for(i = 1; i <= CurrentDocument.GetValue(\"Number_of_Accordions_TopSec\"); i++){ %\}\n <!--\n {% accordion = CurrentDocument.GetValue(\"Accordion\" + i + \"_TopSec\"); %\}\n -->\n {% if(accordion != null){ %\}\n <!--\n {% accordionName = Documents[accordion].DisplayName; %\}\n -->\n \n {% accordionName %\}\n \n {%if(CurrentDocument.GetValue(\"Accordion\" + i + \"_Text_TopSec\",null) != null){CurrentDocument.GetValue(\"Accordion\" + i + \"_Text_TopSec\",null)}%\}\n \n {% Documents[accordion].Children.ClassNames(\"customProducts_Literature.Literature_Products\").WithAllData.ApplyTransformation(\"customProducts_Literature.Literature_Products.grid_literaturecentre\") #%\}\n \n {% if(DocumentCulture == \"en-us\"){ %\}\n {% GetResourceString(\"custom.lblPlaceOrder\", DocumentCulture) %\}\n {% } %\}\n \n \n {% } %\}\n {% } %\}\n \n {% } %\}\n")) } |(user)alistair|(hash)b4b1e17afefcaa9f79180a29cea7d53923c4c4ccd2578a9f1d08011e83239a25' with overtime 00:00:00.1445290. Check the expression for infinite loops or increase the timeout.
at CMS.MacroEngine.ExpressionEvaluator.CheckForTimeout()
at CMS.MacroEngine.ExpressionEvaluator.EvaluateInternal(Boolean& match, Boolean& securityPassed)
at CMS.MacroEngine.ExpressionEvaluator.PrintToConsole(Boolean& match, Boolean& securityPassed)
at CMS.MacroEngine.ExpressionEvaluator.EvaluateInternal(Boolean& match, Boolean& securityPassed)
at CMS.MacroEngine.ExpressionEvaluator.EvaluateInternal(Boolean& match, Boolean& securityPassed)
at CMS.MacroEngine.ExpressionEvaluator.EvaluateCondition(Boolean& match, Boolean& securityPassed, DataRow drLogItem, DateTime evaluationStarted)
at CMS.MacroEngine.ExpressionEvaluator.EvaluateInternal(Boolean& match, Boolean& securityPassed)
at CMS.MacroEngine.ExpressionEvaluator.EvaluateCompoundExpression(Boolean& match, Boolean& securityPassed)
at CMS.MacroEngine.ExpressionEvaluator.EvaluateInternal(Boolean& match, Boolean& securityPassed)
at CMS.MacroEngine.ExpressionEvaluator.Evaluate()
at CMS.MacroEngine.MacroResolver.ResolveMacroExpression(ResolveExpressionSettings settings)

I have attempted to add |(timeout)2000 to the end of the macro to increase the time out. I have also tried greater numbers, but nothing seems to get this transformation to work on our production site. Please help.

Correct Answer

Peter Mogilnitski answered on January 17, 2019 19:47

if timeout doesnt help - this because your query is not efficient. I usually try to avoid .WithAllData (it is really inefficient) In your case you probably need to create a custom macro use DocumentHelper to make your query more efficient

2 votesVote for this answer Unmark Correct answer

Recent Answers


Zach Perry answered on January 17, 2019 08:31

I am guessing your production environment has more documents than your staging environment?

Sounds like you have a repeater with a transformation that makes a database call for each item in the repeater, which is bad for performance.

I would copy/stage your content from Production to your dev environment so you have an accurate test, and instead of using a macro like you are to pull children I would switch over to a Hierarchical viewer and get all your data in one Database call.

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on January 17, 2019 14:54

What Zach said. In addition, take your macro and execute it in System > Macros > Console with some static values and see what your results are.

0 votesVote for this answer Mark as a Correct answer

Ron Truex answered on January 17, 2019 15:42

That is my issue I have had with Macros. I know from a lot of standpoint Macros are recommended, but I have reworded a few macros to be aspx and it fixes the issue because of the way its processed.

0 votesVote for this answer Mark as a Correct answer

Juraj Ondrus answered on January 17, 2019 20:20

I agree with what Peter said - sometimes it is just better to create a custom macro method and get the data and just the date you want. Macros are mighty but not all-mighty and cannot cover every single, custom need.

0 votesVote for this answer Mark as a Correct answer

Alistair DeJonge answered on January 21, 2019 23:17

I have re-written the transformation to this:

{% if(CurrentDocument.GetValue("Show_LiteratureCentre",false) && CurrentDocument.GetValue("ShowTopContent",false)){ %}
    {% if(CurrentDocument.GetValue("Accordion1_TopSec",null) != null){ %}
        <div class="accordion-container">
        {% for(i = 1; i <= CurrentDocument.GetValue("Number_of_Accordions_TopSec",0); i++){ %}
        <!--
        {% 
        accordion = CurrentDocument.GetValue("Accordion" + i + "_TopSec",null);
        accordionDoc = Documents[accordion];
        accordionChildren = accordionDoc.Children.ClassNames("customProducts_Literature.Literature_Products"); 
        %}
        -->
        {% if(accordion != null){ %}
            <!--
            {% accordionName = accordionDoc.DisplayName; %}
            -->
            <div>
            <h3 id="header{% i %}_Lit"><a href="#" onclick="return false;">{% accordionName %}</a></h3>
            <ul id="Accordion{% i %}_Lit">
                <div style="position:relative;">
                    {% foreach (child in accordionChildren){child.ApplyTransformation("customProducts_Literature.Literature_Products.grid_literaturecentre")|(timeout)10000} #%}
                </div>
                {% if(DocumentCulture == "en-us"){ %}
                    <div class="LitOrder"><a href="#" class="button--alt-black">{% GetResourceString("custom.lblPlaceOrder", DocumentCulture) %}</a></div>
                {% } %}
            </ul>
         </div>
        {% } %}
    {% } %}
    </div>
    {% } %}
{% } #%}

I will probably have to go with a custom macro, or something, but I wanted to know why this exact same transformation works on an exact clone of our production environment, but it still does not work on production. We don't get a lot of users at one time... maybe 50-100.

0 votesVote for this answer Mark as a Correct answer

Brenden Kehren answered on January 21, 2019 23:29

What you're doing is essentially nesting 2 repeaters/queries in a single repeater/query; not ideal from a performance standpoint.

Why not use a universial viewer with different level transformations? Even creating a custom macro won't help with performance because you're still going to call a query against the child pages. How many pages/nodes do you have in your content tree?

0 votesVote for this answer Mark as a Correct answer

Alistair DeJonge answered on January 22, 2019 15:52

For that particular transformation, the children are custom content only pages that range from 5 - 25 depending on the site tree folder (AKA accordion) chosen. On the page that it is not working, there are 10 accordions to loop through. I realize that it's a lot of processing, but what I don't really understand is that it had no problem with this transformation in Kentico 9 (which we recently upgrade from), and it doesn't seem to have any problem on our staging site (which has the exact same content).

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.