Question
· Mar 4, 2020

Request Timeout in Business Processes

I want to send requests from custom BP with timeout and be able to understand that timeout event happened.

I thought that I need to implement OnTimeout method in my process (in either caller or callee), however it seems like OnTimeout  is never called.

Let's say we have this parent process:

Class Timeout.Parent Extends Ens.BusinessProcess [ ClassType = persistent ]
{
Method OnRequest(pRequest As Ens.StringContainer, Output pResponse As Ens.StringContainer) As %Status {
    set sc = ..SendRequestSync("Timeout.Child", pRequest, .pResponse, 5)
    if ($$$ISOK(sc) && ('$isObject(pResponse))) {
        set text = "Caught timeout"
        $$$TRACE(text)
        set pResponse = ##class(Ens.StringContainer).%New(text)
    }
    quit sc
}
Method OnTimeout(request As Ens.StringContainer, ByRef response As Ens.StringContainer, callrequest As Ens.StringContainer, pCompletionKey As %String) As %Status
{
    set text = "TIMEOUT PARENT"
    $$$TRACE(text)
    set response = ##class(Ens.StringContainer).%New(text)
    quit $$$OK
}
}  

And this child process:

Class Timeout.Child Extends Ens.BusinessProcess [ ClassType = persistent ]
{
Method OnRequest(pRequest As Ens.StringContainer, Output pResponse As Ens.StringContainer) As %Status
{
    hang 10
    set text = "OnRequest CHILD"
    $$$TRACE(text)
    set pResponse = ##class(Ens.StringContainer).%New(text)
    quit $$$OK
}

Method OnTimeout(request As Ens.StringContainer, ByRef response As Ens.StringContainer, callrequest As Ens.StringContainer, pCompletionKey As %String) As %Status
{
    set text = "TIMEOUT CHILD"
    $$$TRACE(text)
    set response = ##class(Ens.StringContainer).%New(text)
    quit $$$OK
}
}

However, neither OnTimeout method gets called. Why?

I've found a workaround: if SendRequestSync returns $$$OK but response is empty that means we got a timeout error.

Is there a better way to detect timeouts in Sync calls?

Additionally, how can we catch a timeout with async calls? SendRequestAsync doesn't have a timeout parameter at all.

Code sample.

Discussion (2)0
Log in or sign up to continue

Hi

You can set a timeout for async calls by calling the SetTimer() method.

See below an example with an async call where the OnTimeout gets called:

 Method OnRequest(pRequest As Ens.Request, Output pResponse As Ens.Response) As %Status
{
  SET t=$$$OK
  SET t=..SendRequestAsync("BOout",pRequest,1,"RequestCompletionKeyOne",)
  Set tSC = ..SetTimer("PT10S")
  Quit t
}

 
Method OnResponse(request As %Library.Persistent, ByRef response As %Library.Persistent, callrequest As %Library.Persistent, callresponse As %Library.Persistent, pCompletionKey As %String) As %Status
{
  if pCompletionKey="RequestCompletionKeyOne"
  {
    $$$TRACE("Response for request with CompletionKey RequestCompletionKeyOne has been received")
  }
  Quit $$$OK
} 



Method OnTimeout(request As %Library.Persistent, ByRef response As %Library.Persistent, callrequest As %Library.Persistent, pCompletionKey As %String) As %Status
{
// Subclass responsibility
  $$$LOGWARNING(" Timeout Occurred")
  Quit $$$OK
}

Regards

Stelios