Asynchronous calls using service callout policy

ahemanna
Participant II

According to the docs "when service callout policy <Response> tag is omitted, the API proxy does not wait for the response and continues with the subsequent steps", thus making it an asynchronous call.

To test this I created two API proxies. One to mock(say mock API) a backend service(That takes about 30 seconds to respond) and the other(say client API) to call this API using service callout policy. Below is my service callout policy

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ServiceCallout async="false" continueOnError="false" enabled="true" name="SC-CallMocky">
    <DisplayName>SC-CallMocky</DisplayName>
    <Properties/>
    <Request>
        <Set>
            <Verb>GET</Verb>
        </Set>
        <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    </Request>
    <Response>calloutResponse</Response> <!--to be removed to make it an async call-->
    <HTTPTargetConnection>
        <Properties>
            <Property name="success.codes">2xx,4xx,5xx</Property>
            <Property name="connect.timeout.millis">120000</Property>
            <Property name="io.timeout.millis">120000</Property>
        </Properties>
        <URL>https://xxxxxxxx-xxxx-test.apigee.net/mocky/slowpoke</URL>
    </HTTPTargetConnection>
</ServiceCallout>

When the <Response> tag is retained I can see the flow works as expected - I can see the trace in the mock API and also the client API takes ~30s to respond.

But when I remove the <Response> tag, the client API responds in about a second but I do not see a trace in the mock API(meaning the mock API was never invoked?).

I understand async calls can be made using JS policy. I wanted to check if this is possible using service callout policy.

The question I've got is, is my understanding about using service callout policy for async calls correct? If yes any pointers as to why my approach to test this isn't working would be really helpful.

Thank you.

Solved Solved
2 19 7,517
1 ACCEPTED SOLUTION

I've tested your scenario and reproduced it here.

When using a ServiceCallout to invoke another Apigee Edge API Proxy in the same org/env, with HTTPTargetConnection and fire-and-forget (no Response configured in the ServiceCallout), what I observe is: the service callout does not always send the outbound request. This seems like a bug.

ref: b/110535186

This can be avoided if you use LocalTarget:

<ServiceCallout name='SC-TargetDelay-Asynch'>
  <Request variable='simpleGetRequest'>
    <Set>
      <Verb>GET</Verb>
    </Set>
  </Request>
  <!-- exclude Response to make this call async -->
  <!--
  <Response>tokenResponse</Response>
  -->

  <LocalTargetConnection>
    <Path>/passthrough1/whatever</Path>
  </LocalTargetConnection>

  <!--
  <HTTPTargetConnection>
    <SSLInfo>
      <Enabled>true</Enabled>
      <IgnoreValidationErrors>false</IgnoreValidationErrors>
    </SSLInfo>
    <Properties>
      <Property name='success.codes'>2xx</Property>
    </Properties>
    <URL>https://MYORG-MYENV.apigee.net/passthrough1</URL>
  </HTTPTargetConnection>
  -->
</ServiceCallout>

I've filed a bug (b/110535186). Because the problem only affects one proxy calling another, and because there is an easy workaround it will be rated at P3.

View solution in original post

19 REPLIES 19

Maybe you have a misunderstanding about how the asynchronous ServiceCallout works.

Your observation is exactly what we expect.

When the <Response> tag is retained I can see the flow works as expected - I can see the trace in the mock API and also the client API takes ~30s to respond.

But when I remove the <Response> tag, the client API responds in about a second but I do not see a trace in the mock API.

Yes, there's no Trace, because the asynchronous call is "fire and forget". Apigee Edge initiates the outbound call, and then immediately continues executing subsequent policies. There's no chance for the subsequent API Proxy flow to obtain the response from the outbound call, because Apigee Edge isn't waiting for the response.

Hi Dino, in this scenario Abhiram is using two api proxies. Let's say one is ServiceCallout proxy and other is Mock proxy.

In ServiceCallout proxy, he is using a service callout policy which doesn't have <Response> tag & also calling the Mock proxy using HTTPTargetConnection tag.

Now the SC policy will be asynchronously executed, when this is executed it should call the Mock proxy right? At this point when SC policy is asynchronously executed he cannot see any Trace call in Mock proxy.

Yes, that is my understanding too.

Ahh, thank you. I wasn't clear on the situation. This helps.

Yes, I understand it is fire and forget. But because the endpoint I'm calling from the SC is another API proxy I should be able to trace that request right?

it is a separate proxy...and it should be traceable independently and doesn't depend upon fire and forget or sync.

I've tested your scenario and reproduced it here.

When using a ServiceCallout to invoke another Apigee Edge API Proxy in the same org/env, with HTTPTargetConnection and fire-and-forget (no Response configured in the ServiceCallout), what I observe is: the service callout does not always send the outbound request. This seems like a bug.

ref: b/110535186

This can be avoided if you use LocalTarget:

<ServiceCallout name='SC-TargetDelay-Asynch'>
  <Request variable='simpleGetRequest'>
    <Set>
      <Verb>GET</Verb>
    </Set>
  </Request>
  <!-- exclude Response to make this call async -->
  <!--
  <Response>tokenResponse</Response>
  -->

  <LocalTargetConnection>
    <Path>/passthrough1/whatever</Path>
  </LocalTargetConnection>

  <!--
  <HTTPTargetConnection>
    <SSLInfo>
      <Enabled>true</Enabled>
      <IgnoreValidationErrors>false</IgnoreValidationErrors>
    </SSLInfo>
    <Properties>
      <Property name='success.codes'>2xx</Property>
    </Properties>
    <URL>https://MYORG-MYENV.apigee.net/passthrough1</URL>
  </HTTPTargetConnection>
  -->
</ServiceCallout>

I've filed a bug (b/110535186). Because the problem only affects one proxy calling another, and because there is an easy workaround it will be rated at P3.

@Dino-at-Google
Thank you for this. When I use local target connection I can see the SC is making an async call. However when I moved my mock API to a different org and used HTTPTargetConnection I observed that even after removing the <Response> tag the SC policy waits for the mock API to respond. Meaning it is not being async.

The reason we are using HTTPTargetConnection is we have a mail notification service we would call from our API and we do not want to build another wrapper over it to make a local target call. I understand we can still use Js policy, but we would prefer SC if we could get it to work.

Yes I understand. At this point, you have multiple workarounds, so you should be unblocked.

If you want to track the status of the related bug, you need to open a support ticket and tell them that. (sorry, there is no way to just "subscribe" to the bug without contacting Apigee Edge support)

Followed the following approach to achieve asynchronous logging:

I was using a Service Callout to invoke the logging external service.

To make it asynchronous excluded the response tag, however time taken was still taking 300ms to 500 ms as it was trying to atleast reach the service.

To mitigate this, created a local proxy(AsyncLogger) invoking the external logging service

We invoked this local proxy from the main service without response tag. This reduced the time from 300ms to <1ms.

And the logs were handled by the AsyncLogger

I don't think this problem is only limited to apiegee target in the same org/env, rather i could see its not making call to any external URL if it is configured in HTTPTargetConnection.
I am trying writing in bucket and nothing happening however when i include the response element, it works.
Good if we have some resolution.

Is there a target completion date for this bug? We are also experiencing issues due to the fact that only LocalTargetConnection service callouts can take advantage of the async functionality.

I don't have a target date. I'm bumping up the priority of this issue now. Will revert back.

The problem has been diagnosed and fixed. The fix will be available in OPDK 19.06, and also in the public cloud (SaaS) in the next release, which is currently tentatively scheduled for June 2019.

Hi Dino - still I am facing the same issue in SC by using HttpTargetconnection and endpoint is configured in Targetserver. Please help!

You'll have to mention the version of Apigee you are using. As I noted, it's been fixed, a couple years ago.  If you are using an older version of Apigee, you won't have the fix. 

If youhave a current version of Apigee, then I suggest contacting Apigee support to report this problem! 

Thanks for the response. I have implemented LocalTargetConnection in SC policy and is working as expected.

@s888 ,

We are also having similar use case for async in SC Policy, but it is not working as expected. Could you please share the woking SC policy here (by masking/removing your sensitive information)

Don't ask new questions as comments on 3 year old threads.  

If you have a "similar" question or problem, please ask new question. The button that allows you to ask a new question is in the upper right hand corner of this website.

If you want to, when you post your new question, you can link to this question in your new question.  But your question should not be "I have the same problem as discussed here (LINK).  You need to provide YOUR specific details as to 

  • what you are trying to accomplish
  • what configuration you are using
  • what results you are observing
  • what results you expect to observe
  • and if it is not obvious, describe the difference in those two (expected vs observed)