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 = -1
} Else {
Set ..FailureTimeout = 60
}
}
ObjectScriptObjectScript
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
Here you can find a similar question from @Evgeny Shvarov
https://community.intersystems.com/post/how-can-i-change-production-sett...
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:
Hi @Pietro Di Leo !
In the discussion provided by @Luis Angel Pérez Ramos there is another code by @Alex Woodhead
you can use that will change not only "undefault" settings:
set pSettings(<itemName>,<target>,<settingName>)=<settingValue> do ##class(Ens.Production).ApplySettings(<productionName>, .pSettings)
Or install the package - it should help.
One approach that might be suitable is to have a look at overriding method OnFailureTimeout in the sub-class, which seems for this purpose.
Anticipate the ..FailureTimeout value will need to be more than 0 for OnFailureTimeout to be invoked.
Another area to review could be overriding OnGetReplyAction, to extend the retry vocabulary.
Thank you Alex, how can I modify the OnFailureTimeout method for my purpose? I can find only a little documentation
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
Route to two BOs ("Normal" and "High" priority) with different FailureTimeout. Use SDS to keep other settings in sync.