Question
· Sep 11, 2023

Is it possible to dynamically adjust the FailureTimeout of a Business Operation?

Hi everyone, 

I'm working on a Business Operation whit an HTTP Outbound Adapter and I would like to know if is possible to adjust the FailureTimeout value based on the incoming message type. For example, I would like to have a FailureTimeout of 60 seconds for the standard operations and a FailureTimeout of -1 (wait forever) for few special operations that absolutely need a response. 

Can we dynamically modify the FailureTimeout through code, based on either the incoming message type or a specified parameter?n the incoming message type or depending by a parameter?

For example, something like: 

If ..RetryCount = 1 {
    If pRequest.severity = "high" {
        Set ..FailureTimeout = -1Else {
        Set ..FailureTimeout = 60
    }
}

I've tried but I wasn't able to set the FailureTimeout by code. This seems logic to me because the FailureTimeout timer starts when the first message is sent and it would be strange if it could be changed runtime. However, I'd like to clarify that my intention is not to modify the FailureTimeout dynamically with every iteration of the function, but rather just at the first iteration, based on specific conditions. 

Should I keep trying with this idea, or is it better to create a second Business Operations process to handle those special messages which will be set with a fixed FailureTimeout of -1?

Thanks

Product version: IRIS 2021.1
Discussion (10)4
Log in or sign up to continue

Thank you Luis, this was useful. 

However, I've encountered two issues while adapting the code you provided to my specific situation:

if ..RetryCount = 1 {
    ; Find the production
    #dim p As Ens.Config.Production
    Set p = ##class(Ens.Config.Production).%OpenId("ProductionName")
    if '$isObject(p) {
        $$$LOGERROR("Production not found")
        quit
    }
    #dim item As Ens.Config.Item
    #dim sett As Ens.Config.Setting
    ; Loop over all the elements of the production 
    for i=1:1:p.Items.Count() {
        s item=p.Items.GetAt(i)
        ; Find the desired business component
        if (item.Name="Component1Name"
            ||(item.Name="Component2Name"))
            {
            $$$LOGINFO(item.Name_" found")
            ; Explore settings
            for s=1:1:item.Settings.Count() {
                set sett=item.Settings.GetAt(s)
                ; Search for the FailureTimeout
                if (sett.Name="FailureTimeout"){
                    $$$LOGINFO(sett.Name_" found")
                    ; Change the valure of the FailureTimeout based on the Severity
                    If Severity = "high" {
                        set sett.Value = -1
                    } Else {
                        set sett.Value = 30
                    }
                } 
            }
        }
    } 
    Set sc = p.%Save()
    If $$$ISERR(sc) { 
        $$$LOGERROR($System.Status.GetErrorText(sc))
        quit
    } 
}

With this code, I can adjust the FailureTimeout value based on the Severity parameter, and the updated value is correctly shown in the Production settings. Nevertheless, there are a couple of issues:

  1. This functionality only applies to modified settings, as it doesn't affect settings with default values, which are not included in the loop (set sett=item.Settings.GetAt(s)). Consequently, it's necessary to modify the settings at least once to ensure they are processed within the loop.
  2. While the FailureTimeout value gets updated, the sending procedure uses this updated value for the subsequent message, not the current one. As a consequence, the current message continues to operate with the outdated FailureTimeout value, causing the sending (and re-sending) procedure to deviate from the desired timeouts. 

Ciao Pietro,

I'm afraid you cannot change FailureTimeout "at the first iteration", however, for the specific case you describe, in the Business Operation you can override the method OnFailureTimeout() and there programmatically change the default behavior when the FailureTimeout has been reached. Something like:

/// Override this method to provide custom handling of retry / failure timeout.<p/>
/// Set ..Retry=1 to override normal error return and re-evaluate flag properties.<p/>
/// Return 0 to skip further (default) FailureTimeout processing, 1 to perform default processing.
Method OnFailureTimeout(pRequest As %Library.Persistent, Output pResponse As %Library.Persistent, ByRef pSC As %Status) As %Boolean
{
	If pRequest.severity = "high" {
		Set ..Retry=1
		Quit 0
	} Else {
		Quit 1
	}
}

This is just a simple example, you may want to test/check pSC....

Give it a try and let us know.

Ciao,

Enrico

Hi Enrico,

Thank you for the response. I've tried both adding an OnFailureTimeout method in my custom BO and directly modifying the OnFailureTimeout method inside the Ens.BusinessOperation. However, in the first case, nothing happens, while in the second case, the error "ERROR #5883: Item 'Ens.BusinessOperation' is mapped from a database that you do not have write permission on" occurs

I was surprised that overriding the OnFailureTimeout() in the custom BO class did not work! According to the description that was definitely the way to go. But it indeed does not work(ed).

I opened a WRC and it turned out that there is a bug "around" the OnFailureTimeout() implementation in Ens.BusinessOperation.

So, if anyone need to implement OnFailureTimeout()  with Set ..Retry=1, first it requires to contact WRC, explain the problem and reference DP-426250 to get the fix.

Enrico