<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Preformatted Char";
        margin:0in;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New",serif;}
tt
        {mso-style-priority:99;
        font-family:"Courier New",serif;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.HTMLPreformattedChar
        {mso-style-name:"HTML Preformatted Char";
        mso-style-priority:99;
        mso-style-link:"HTML Preformatted";
        font-family:Consolas;}
span.EmailStyle22
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal">Liviu,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thank you. This makes complete sense now and the documentation updates are excellent. Thanks as well for the workaround suggestion; we will investigate whether it is necessary. You do make a good point in the docs about TCP connection reuse
 in the workers, which shows my example as a bit of an extreme case. In practical use it is more likely the connection would exist and the transfer would timeout instead, which would be async.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Even though the example may be extreme, in the current world of cloud computing having the remote server “disappear” without closing TCP connections is becoming a much more common concern. Cloud instances can and do just disappear and the
 connections will hang; cloud networks have issues and can leave connections hung as well. We have been wrestling with these issues with the db_postgres and db_virtual modules for some time and have an open ticket for it now. While it is impossible to avoid
 some service impairment when a necessary remote component is no longer available, having the entire call processing application block on the resource is also not a very good response. We are always looking for better ways to gracefully handle the unexpected.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks for the time and quick responses!<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="color:black">Ben Newlin </span><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><span style="font-size:12.0pt;color:black">From: </span></b><span style="font-size:12.0pt;color:black">Users <users-bounces@lists.opensips.org> on behalf of Liviu Chircu <liviu@opensips.org><br>
<b>Reply-To: </b>OpenSIPS users mailling list <users@lists.opensips.org><br>
<b>Date: </b>Thursday, June 27, 2019 at 5:05 AM<br>
<b>To: </b>OpenSIPS users mailling list <users@lists.opensips.org><br>
<b>Subject: </b>Re: [OpenSIPS-Users] Rest Client Async operation<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal">On 26.06.2019 17:48, Ben Newlin wrote:<o:p></o:p></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Thanks again for the info. I think what you are saying is that the async operation is not launching a new process to handle the called function, but is performing the function in
 the original worker thread and only taking advantage of any suspend/resume or polling functionality already exposed by the underlying function itself.
<o:p></o:p></p>
</blockquote>
<p class="MsoNormal"><tt><span style="font-size:10.0pt">Just to clear this up:  the underlying functions themselves need not offer any polling functionality,</span></tt><span style="font-size:10.0pt;font-family:"Courier New",serif"><br>
<tt>they just need to meet two criteria: (1) be non-blocking; (2) provide a valid fd for the async engine to poll on.</tt></span><o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"><tt><span style="font-size:10.0pt">Any blocking I/O functionality, be it within libcurl, MySQL, etc. that meets the above can be adapted to</span></tt><span style="font-size:10.0pt;font-family:"Courier New",serif"><br>
<tt>work with the async engine available in OpenSIPS 2.1+.</tt></span><br>
<br>
<o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">I understand that the practicalities of the implementation in OpenSIPS may have required this design, but I must re-iterate that these limitations need to be documented very carefully
 as they are very important to understand when designing OpenSIPS scripts with async functionality and are not described anywhere. I could not find anywhere in the documentation that indicates that async operations can potentially still block the original worker
 thread and block call processing. The closest is:<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">“The current OpenSIPS worker will launch the asynchronous operation, after which it will continue to process other pending tasks”
<o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto"> <o:p></o:p></p>
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">But this provides no elaboration on what it means for the worker to “launch” the operation, and more importantly it does not indicate that the launching itself can block, which
 is the key issue here.<o:p></o:p></p>
</blockquote>
<p class="MsoNormal"><tt><span style="font-size:10.0pt">Agreed - will try to find a way to integrate this corner-case into the docs, somehow.</span></tt><br>
<br>
<o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal" style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">As I said, this unfortunately makes async processing mostly useless for us. For both DB and REST queries if only the data transfer is async then it is only useful when the data
 being transferred is extremely large or prone to delays/jitter. Such transfers should be avoided during realtime processing whether async or not, as they will still delay the individual call even if not others. For small payloads, like the single JSON object
 common in REST responses, it is the connection itself that is the concern. Once connected, running the data transfer in async mode represents no real gain.<o:p></o:p></p>
</blockquote>
<p class="MsoNormal"><tt><span style="font-size:10.0pt">Then I recommend you stop using rest_client, which currently optimizes system resource</span></tt><span style="font-size:10.0pt;font-family:"Courier New",serif"><br>
<tt>usage for setups where the TCP connect cannot possibly ever hang, and resort to forking</tt><br>
<tt>a process for each HTTP request, using a construct such as:</tt></span><o:p></o:p></p>
<p><tt><span style="font-size:10.0pt">    async(exec("curl your_connect_hanging_http_endpoint"), resume_route);</span></tt><o:p></o:p></p>
<p><tt><span style="font-size:10.0pt">Although forking a process for each request is a costly operation which will</span></tt><span style="font-size:10.0pt;font-family:"Courier New",serif"><br>
<tt>eat more system resources during normal operation, at least this solution optimizes</tt><br>
<tt>for the worst case, when the HTTP server is down.  In this latter case, the</tt><br>
<tt>throughput of your SIP server won't be hindered that much, as the hanging connect</tt><br>
<tt>will be done asynchronously.</tt></span><o:p></o:p></p>
<p><tt><span style="font-size:10.0pt">Best regards,</span></tt><o:p></o:p></p>
<pre>Liviu Chircu<o:p></o:p></pre>
<pre>OpenSIPS Developer<o:p></o:p></pre>
<pre><a href="http://www.opensips-solutions.com">http://www.opensips-solutions.com</a><o:p></o:p></pre>
</div>
</body>
</html>