You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WSO2 MI 4.0.0中Iterate中介器首调用失败后终止后续调用问题

解决方案:在WSO2 MI 4.0.0中实现Iterate失败即终止

核心思路

默认Iterate中介器会预先生成所有子线程,即便设置isError属性,后续子线程仍会启动(仅被丢弃)。要实现第一个API调用失败就直接停止后续迭代、不启动新线程,需结合异常抛出+父序列捕获中断的机制,同时确保Iterate以顺序模式执行(sequential="true")。

修改后的完整序列代码

<?xml version="1.0" encoding="UTF-8"?>
<sequence name="Iterator" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
    <property name="isError" scope="operation" type="BOOLEAN" value="false"/>
    <!-- 捕获子序列抛出的异常,终止后续迭代 -->
    <catch>
        <property name="isError" scope="operation" type="BOOLEAN" value="true"/>
        <log level="ERROR">
            <property name="message" value="迭代执行中断,因API调用失败"/>
        </log>
        <!-- 返回错误响应给客户端 -->
        <payloadFactory media-type="json">
            <format>{"error": "API调用失败,迭代已终止"}</format>
            <args/>
        </payloadFactory>
        <respond/>
    </catch>
    <iterate continueParent="false" expression="json-eval($)" sequential="true">
        <target>
            <sequence>
                <log>
                    <property expression="get-property('operation','isError')" name="filter_flag"/>
                </log>
                <filter regex="false" source="get-property('operation','isError')">
                    <then>
                        <property expression="json-eval($.quantity)" name="QUANTITY" scope="default" type="STRING"/>
                        <property expression="json-eval($.price)" name="FINAL_PRICE" scope="default" type="STRING"/>
                        <property expression="json-eval($.final_price)" name="PRICE" scope="default" type="STRING"/>
                        <script language="js"><![CDATA[var log = mc.getServiceLog();
                            log.info("Logging inside Script Mediator");
                            var value1 = mc.getProperty("FINAL_PRICE");
                        var value2 = mc.getProperty("PRICE");
                        var divide = value1 / value2;
                       log.info("divide   "+divide);
                       var formattedNumber = parseFloat(divide.toFixed(2));
                        log.info("result   "+formattedNumber);
                        log.info("PRICECOMPARE"+(value1===divide));
                        mc.setProperty("LIST_PRICE", formattedNumber);
                       mc.setProperty("PRICECOMPARE", value1===divide);]]></script>
                        <filter regex="false" source="boolean($ctx:PRICECOMPARE)">
                            <then>
                                <payloadFactory media-type="json">
                                    <format>{&amp;#xd;
                          "line_item": {&amp;#xd;
                              "quantity": $1,&amp;#xd;
                              "list_price": $2&amp;#xd
                            }&amp;#xd;
                        }</format>
                                    <args>
                                        <arg evaluator="xml" expression="$ctx:QUANTITY"/>
                                        <arg evaluator="xml" expression="$ctx:LIST_PRICE"/>
                                    </args>
                                </payloadFactory>
                                <endpoint>
                                    <http format="soap11" method="GET" uri-template="http://myendpoint/services/GuestIdentityService"/>
                                </endpoint>
                                <property expression="get-property('axis2', 'HTTP_SC')" name="HTTP_STATUS_CODE" scope="default" type="STRING"/>
                                <log>
                                    <property expression="json-eval($)" name="status"/>
                                </log>
                                <filter xpath="$axis2:HTTP_SC != '200'">
                                    <then>
                                        <property name="isError" scope="operation" type="BOOLEAN" value="true"/>
                                        <!-- 抛出异常,触发父序列的catch,终止Iterate后续迭代 -->
                                        <throw faultcode="API_ERROR" faultreason="API调用返回非200状态码"/>
                                    </then>
                                    <else/>
                                </filter>
                            </then>
                            <else/>
                        </filter>
                    </then>
                    <else>
                        <drop/>
                    </else>
                </filter>
            </sequence>
        </target>
    </iterate>
    <!-- 所有迭代正常完成时返回成功响应 -->
    <filter source="get-property('operation','isError')" regex="false">
        <then>
            <payloadFactory media-type="json">
                <format>{"status": "所有迭代执行完成"}</format>
                <args/>
            </payloadFactory>
            <respond/>
        </then>
    </filter>
</sequence>

关键修改点说明

  • 设置continueParent="false":确保父序列等待Iterate的所有子线程执行完成后再继续,避免提前返回响应。
  • 添加<catch>中介器:捕获子序列抛出的异常,立即设置错误状态并返回错误响应,同时终止Iterate的后续迭代。
  • 错误分支添加<throw>:当API调用失败时,抛出异常触发父序列的中断逻辑,而非仅设置isError,以此阻止Iterate生成后续子线程。
  • 调整响应逻辑:区分正常完成和错误中断两种情况,分别返回对应响应。

注意事项

  • 必须保持Iterate的sequential="true":仅在顺序执行模式下,子线程的异常才能及时触发父序列的中断,避免并行线程继续执行。
  • operation范围的isError属性:用于在正常流程中判断是否出现错误,保证最终响应的正确性。

内容的提问来源于stack exchange,提问作者sathish Sankarzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:41:10