Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Design Challenges: building a REST API which calls a 3rd Party REST API

Received: by 10.216.203.96 with SMTP id e74mr69542weo.1.1349248864256;
        Wed, 03 Oct 2012 00:21:04 -0700 (PDT)
X-BeenThere: api-craft@googlegroups.com
Received: by 10.180.73.226 with SMTP id o2ls3354010wiv.0.gmail; Wed, 03 Oct
 2012 00:20:55 -0700 (PDT)
Received: by 10.180.94.98 with SMTP id db2mr3419855wib.2.1349248855514;
        Wed, 03 Oct 2012 00:20:55 -0700 (PDT)
Received: by 10.180.94.98 with SMTP id db2mr3419854wib.2.1349248855480;
        Wed, 03 Oct 2012 00:20:55 -0700 (PDT)
Return-Path: <b...@nocarrier.co.uk>
Received: from mail-we0-f171.google.com (mail-we0-f171.google.com [74.125.82.171])
        by gmr-mx.google.com with ESMTPS id hm1si373422wib.3.2012.10.03.00.20.55
        (version=TLSv1/SSLv3 cipher=OTHER);
        Wed, 03 Oct 2012 00:20:55 -0700 (PDT)
Received-SPF: neutral (google.com: 74.125.82.171 is neither permitted nor denied by best guess record for domain of b...@nocarrier.co.uk) client-ip=74.125.82.171;
Authentication-Results: gmr-mx.google.com; spf=neutral (google.com: 74.125.82.171 is neither permitted nor denied by best guess record for domain of b...@nocarrier.co.uk) smtp.mail=...@nocarrier.co.uk
Received: by weys43 with SMTP id s43so8053589wey.16
        for <api-craft@googlegroups.com>; Wed, 03 Oct 2012 00:20:55 -0700 (PDT)
        d=google.com; s=20120113;
        h=from:content-type:message-id:mime-version:subject:date:references
         :to:in-reply-to:x-mailer:x-gm-message-state;
        bh=oyOcBEJiBiRBlnbK6KONg3h1JnN1u/YKgpzljGk9K5Y=;
        b=XleMmmBQjTgkLE7o085bATaJ1TMlBd+SBaBF02FJFpsZCXgCs6VAFSa0Ahb3iquIgx
         xpV4dZ11SkJSvvG+UqTpPtyerJ+Dunl2MBKDDMcnSByevyNALL7xZvWRMea+hnqy5G1F
         NSRlwrrF+hZ3OrUM7y4Fzd6xcAxbKzysY+Bq0lZXM859EkUXCIAQlBjK7Ry/QdsBWyar
         ETtWFBnoG74/lbK0dtZ1UtAkQ9JoCEY9BOudUBYxN0mZdoTL/abTi7KMtllhFAzn3KMp
         riJaNnGzEnJ5TqnMbP1QTSl14zsktke32hVU+L+2UWoYckr3UhpfC7BXn86MssTxbldQ
         ScYQ==
Received: by 10.180.78.102 with SMTP id a6mr27429553wix.20.1349248855085;
        Wed, 03 Oct 2012 00:20:55 -0700 (PDT)
Return-Path: <b...@nocarrier.co.uk>
Received: from [172.20.10.3] (92.40.254.27.threembb.co.uk. [92.40.254.27])
        by mx.google.com with ESMTPS id dm3sm6909462wib.3.2012.10.03.00.20.52
        (version=TLSv1/SSLv3 cipher=OTHER);
        Wed, 03 Oct 2012 00:20:54 -0700 (PDT)
From: Ben Longden <b...@nocarrier.co.uk>
Content-Type: multipart/alternative; boundary="Apple-Mail=_7FFE254E-52F7-44B1-9971-DC3A37AE3D87"
Message-Id: <0B1FF412-675F-42D7-A1F9-0122B5D3E...@nocarrier.co.uk>
Mime-Version: 1.0 (Mac OS X Mail 6.1 \(1498\))
Subject: Re: [api-craft] Design Challenges: building a REST API which calls a 3rd Party REST API
Date: Wed, 3 Oct 2012 08:20:51 +0100
References: <ec08fee6-dcf6-4d06-8589-a94a62288181@googlegroups.com> <CAMZMjeaq0G2=VGykysjqP9Q=vdMU7TwNJGPH2hmExgjnVUg...@mail.gmail.com> <3bb88127-0e37-42ba-9cfe-f09066069ee8@googlegroups.com> <2a305cd6-39ed-45b8-93ef-bc9716ec69c5@googlegroups.com> <e60161f4-3cde-4338-bd6a-2ccc623c132d@googlegroups.com>
To: api-craft@googlegroups.com
In-Reply-To: <e60161f4-3cde-4338-bd6a-2ccc623c132d@googlegroups.com>
X-Mailer: Apple Mail (2.1498)
X-Gm-Message-State: ALoCoQlhyxUqZ3eb1FebZO3GqUIHe+1oqb3tveechDC3Gvi5C0+UOTHECAzGT+OmZcFUVrPtXM/t


--Apple-Mail=_7FFE254E-52F7-44B1-9971-DC3A37AE3D87
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=iso-8859-1

Hi Andrew,

I've used this Hybrid approach too - having an expected ETA for a =
request so that my API can either return a 'real' response, or a 202 =
(with a link to a 'status' resource for the request). It does add a =
little complexity on the client side as it needs to handle both types of =
response - but it does work well.

You could perhaps minimise the additional complexity by using a =
hypermedia type which supports embedded documents - if the request =
completes (ie, is not queued), embed the result data in the response. If =
it does not complete and returns a 202, the real result could be an =
embedded resource in the status monitor for the queued job. At least for =
both of these response types, you have the same way of retrieving the =
data once it is ready. application/hal+json is one of the formats which =
does support embedded resources in a response, to reduce the 'chatty' =
api syndrome.=20

--
BenLongden
http://nocarrier.co.uk

On 2 Oct 2012, at 21:06, Andrew Little <aalit...@gmail.com> wrote:

> Thanks, Dan.  I like this hybrid approach, too. Ideally, I want to =
keep things very clean on the client side, because there may be many =
applications requiring such additional logic. However, this definitely =
ensures that in most cases (i.e. 80%), we'd get a quick response without =
entering the polling loop.  Nice.
>=20
> Andrew
>=20
> On Tuesday, 2 October 2012 16:23:57 UTC-3, Daniel Crenna wrote:
> One approach that might work well for you is to send your call =
asynchronously, but don't push it to a background queue right away. Give =
it the opportunity to complete quickly. You introduce a touch of =
complexity because clients may get one of two responses depending on the =
latency, but at least you cover 80% of cases and have a graceful way to =
handle the others.
>=20
> On Tuesday, October 2, 2012 1:00:46 PM UTC-4, Andrew Little wrote:
> Thanks for the response, Ronnie.
>=20
> I think I misused long polling.  I was attempting to describe standard =
client server polling: 1. client makes request and server responds with =
ACK, 2. client polls the server until a full response is returned.
>=20
> Here is a significant piece of information that I left out =
unintentionally. In all but exceptional cases, the 3rd party API (in =
this case, Twitter) will respond very quickly and the API calling the =
3rd party will experience almost no delay. So my problem with the =
polling solution is that we're introducing a more complicated polling =
behavior on all client apps to handle the exceptional case in which the =
3rd party API is experiencing delays (perhaps high load situations). I =
believe we could get away with making all calls on the API in a =
synchronous fashion, though have not proven this theory.
>=20
> I like your thoughts on the callback pattern. I'll take a look at that =
as well.
>=20
>=20
> On Tuesday, 2 October 2012 12:36:58 UTC-3, Ronnie Mitra wrote:
> Hi Andrew,
>=20
> My definition of long polling is when a client executes long blocking =
GETs until a response is received.  Is this what you are trying to do?  =
It sounds more like your clients will be executing short GETs to check =
on the status of the response periodically.
>=20
> =46rom the scenario you describe it sounds like requests could take a =
long time to be resolved.  In that case you might consider using a =
callback pattern in which the client becomes a server and waits for a =
response (i.e. the server sends the response message as a new HTTP =
request to the client).  I would classify this pattern as more complex =
for the client than polling, but will likely be less of a =
thread/connection strain on your server if that is important.
>=20
> Stateful connections (like websockets) might also be suggested for =
situations like this, but it doesn't sound like that is the right answer =
here as you don't seem to have a need for bi-directional or low latency =
communication and you would be leaving the realm of HTTP.
>=20
> Personally, I'd choose the polling method as it meets most of your =
criteria. I'm not sure why you think it's not RESTful, but I make a =
point of not going down that road!  Off the top of my head, I think the =
Twilio API has some examples of the callback pattern and Subbu's REST =
cookbook has examples of the polling style.
>=20
> thanks,
> Ronnie
> @mitraman
>=20
>=20
>=20
> On Tue, Oct 2, 2012 at 3:45 PM, Andrew Little <aali...@gmail.com> =
wrote:
>=20
>=20
> I am working with a team tasked with building a REST API which in turn =
makes calls into a 3rd party REST API.  So if I make a call to GET =
followers/ids, then our API will in turn call the 3rd party GET =
followers/ids, then perform some basic processing to the 3rd party =
results before returning to the caller.
>=20
> The challenge identified by the team is that we do not control the =
performance of the 3rd party REST API, and therefore it's a risk to make =
these 3rd party calls in a synchronous manner.  Arguments I have heard =
is that a long running 3rd Party call would keep a thread open for an =
extended period of time and we could start to see outages in high =
traffic periods when 3rd party calls are taking a long time. The =
solution proposed is to move to a long polling/async approach. In this =
approach, the caller of GET followers/ids is immediately returned a =
unique Call ID and then asked to poll for the results.  On the server =
side, the call is processed in a queue. This does certainly release the =
thread, but then requires the callers to poll for results. =20
>=20
> I'm not a seasoned REST API architect, but this "long =
polling"/asynchronous approach does not seem to be the best approach to =
solving the design problem of an API which calls a 3rd party API. =20
>=20
> Wondering if anyone could suggest an alternate solution, or point me =
to some examples in which a REST API does exactly what we're trying to =
achieve.   =20
>=20
> My arguments against long polling:
> not RESTful
> adds complexity to the callers of the REST API
> inconsistent API implementation (mix of sync and async)
> polling may cause performance problems because 1000s of clients are =
constantly making calls (albeit shorter calls)
>=20
> --=20
> You received this message because you are subscribed to the Google =
Groups "API Craft" group.
> To unsubscribe from this group, send email to =
api-craft+...@googlegroups.com.
> Visit this group at http://groups.google.com/group/api-craft?hl=3Den.
> =20
> =20
>=20
>=20
> --=20
> You received this message because you are subscribed to the Google =
Groups "API Craft" group.
> To unsubscribe from this group, send email to =
api-craft+unsubscribe@googlegroups.com.
> Visit this group at http://groups.google.com/group/api-craft?hl=3Den.
> =20
> =20


--Apple-Mail=_7FFE254E-52F7-44B1-9971-DC3A37AE3D87
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html;
	charset=iso-8859-1

<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html =
charset=3Diso-8859-1"></head><body style=3D"word-wrap: break-word; =
-webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Hi =
Andrew,<div><br></div><div>I've used this Hybrid approach too - having =
an expected ETA for a request so that my API can either return a 'real' =
response, or a 202 (with a link to a 'status' resource for the request). =
It does add a little complexity on the client side as it needs to handle =
both types of response - but it does work =
well.</div><div><br></div><div>You could perhaps minimise the additional =
complexity by using a hypermedia type which supports embedded documents =
- if the request completes (ie, is not queued), embed the result data in =
the response. If it does not complete and returns a 202, the real result =
could be an embedded resource in the status monitor for the queued job. =
At least for both of these response types, you have the same way of =
retrieving the data once it is ready. application/hal+json is one of the =
formats which does support embedded resources in a response, to reduce =
the 'chatty' api syndrome.&nbsp;</div><div><br><div =
apple-content-edited=3D"true">
<span class=3D"Apple-style-span" style=3D"border-collapse: separate; =
color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; =
font-variant: normal; font-weight: normal; letter-spacing: normal; =
line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: =
0px; text-transform: none; white-space: normal; widows: 2; word-spacing: =
0px; border-spacing: 0px; -webkit-text-decorations-in-effect: none; =
-webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; =
font-size: medium; "><div style=3D"word-wrap: break-word; =
-webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div =
style=3D"margin: 0px; font-style: normal; font-variant: normal; =
font-weight: normal; font-size: 18px; line-height: normal; font-family: =
'Arial Black'; color: rgb(170, 170, 170); "><div style=3D"margin: 0px; =
font-size: 11px; font-family: Helvetica; ">--</div><div style=3D"margin: =
0px; "><span style=3D"color: rgb(0, 0, 0); ">Ben</span>Longden</div><div =
style=3D"margin: 0px; font-size: 12px; "><a =
href=3D"http://nocarrier.co.uk">http://nocarrier.co.uk</a></div></div></di=
v></span>
</div>

<br><div><div>On 2 Oct 2012, at 21:06, Andrew Little &lt;<a =
href=3D"mailto:aalit...@gmail.com">aalit...@gmail.com</a>&gt; =
wrote:</div><br class=3D"Apple-interchange-newline"><blockquote =
type=3D"cite">Thanks, Dan. &nbsp;I like this hybrid approach, too. =
Ideally, I want to keep things very clean on the client side, because =
there may be many applications requiring such additional logic. However, =
this definitely ensures that in most cases (i.e. 80%), we'd get a quick =
response without entering the polling loop. =
&nbsp;Nice.<div><br></div><div>Andrew<br><br>On Tuesday, 2 October 2012 =
16:23:57 UTC-3, Daniel Crenna  wrote:<blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc =
solid;padding-left: 1ex;">One approach that might work well for you is =
to send your call asynchronously, but don't push it to a background =
queue right away. Give it the opportunity to complete quickly. You =
introduce a touch of complexity because clients may get one of two =
responses depending on the latency, but at least you cover 80% of cases =
and have a graceful way to handle the others.<br><br>On Tuesday, October =
2, 2012 1:00:46 PM UTC-4, Andrew Little wrote:<blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px =
#ccc solid;padding-left:1ex">Thanks for the response, =
Ronnie.<div><br></div><div>I think I misused long polling. &nbsp;I was =
attempting to describe standard client server polling: 1. client makes =
request and server responds with ACK, 2. client polls the server until a =
full response is returned.</div><div><br></div><div>Here is a =
significant piece of information that I left out unintentionally. In all =
but exceptional cases, the 3rd party API (in this case, Twitter) will =
respond very quickly and the API calling the 3rd party will experience =
almost no delay. So my problem with the polling solution is that we're =
introducing a more complicated polling&nbsp;behavior&nbsp;on all client =
apps to handle the exceptional case in which the 3rd party API is =
experiencing delays (perhaps high load situations). I believe we could =
get away with making all calls on the API in a synchronous fashion, =
though have not proven this theory.</div><div><br></div><div>I like your =
thoughts on the callback pattern. I'll take a look at that as =
well.</div><div><br><br>On Tuesday, 2 October 2012 12:36:58 UTC-3, =
Ronnie Mitra  wrote:<blockquote class=3D"gmail_quote" =
style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex">Hi Andrew,<div><br></div><div>My definition of =
long polling is when a client executes long blocking GETs until a =
response is received. &nbsp;Is this what you are trying to do? &nbsp;It =
sounds more like your clients will be executing short GETs to check on =
the status of the response periodically.</div>

<div><br></div><div>=46rom the scenario you describe it sounds like =
requests could take a long time to be resolved. &nbsp;In that case you =
might consider using a callback pattern&nbsp;in which the client becomes =
a server and waits for a response (i.e. the server sends the response =
message as a new HTTP request to the client). &nbsp;I would classify =
this pattern as more complex for the client than polling, but will =
likely be less of a thread/connection strain on your server if that is =
important.</div>

<div><br></div><div>Stateful connections (like websockets) might also be =
suggested for situations like this, but it doesn't sound like that is =
the right answer here as you don't seem to have a need for =
bi-directional or low latency communication and you would be leaving the =
realm of HTTP.</div>

<div><br></div><div>Personally, I'd choose the polling method as it =
meets most of your criteria. I'm not sure why you think it's not =
RESTful, but I make a point of not going down that road! &nbsp;Off the =
top of my head, I think the Twilio API has some examples of the callback =
pattern and Subbu's REST cookbook has examples of the polling =
style.</div>
=
<div><br></div><div>thanks,</div><div>Ronnie</div><div>@mitraman</div><div=
><br></div>
<div><br></div><div><br></div><div><div class=3D"gmail_quote">On Tue, =
Oct 2, 2012 at 3:45 PM, Andrew Little <span =
dir=3D"ltr">&lt;<a>aali...@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 =
.8ex;border-left:1px #ccc solid;padding-left:1ex"><br><br>I am working =
with a team tasked with building a REST API which in turn makes calls =
into a 3rd party REST API. &nbsp;So if I make a call to&nbsp;GET =
followers/ids, then our API will in turn call the 3rd party&nbsp;GET =
followers/ids, then perform some basic processing to the 3rd party =
results before returning to the caller.<div>

<br></div><div>The challenge identified by the team is that we do not =
control the performance of the 3rd party REST API, and therefore it's a =
risk to make these 3rd party calls in a synchronous manner. =
&nbsp;Arguments I have heard is that a long running 3rd Party call would =
keep a thread open for an extended period of time and we could start to =
see outages in high traffic periods when 3rd party calls are taking a =
long time. The solution proposed is to move to a <b>long =
polling/async</b> approach. In this approach, the caller of&nbsp;GET =
followers/ids&nbsp;is immediately returned a unique Call ID and then =
asked to poll for the results. &nbsp;On the server side, the call is =
processed in a queue. This does certainly release the thread, but then =
requires the callers to poll for results. &nbsp;</div>

<div><br></div><div>I'm not a seasoned REST API architect, but this =
"long polling"/asynchronous approach does not seem to be the best =
approach to solving the design problem of an API which calls a 3rd party =
API. &nbsp;</div>

<div><br></div><div><b>Wondering if anyone could suggest an alternate =
solution, or point me to some examples in which a REST API does exactly =
what we're trying to achieve. &nbsp; =
&nbsp;</b></div><div><br></div><div>My arguments against long =
polling:</div>

<div><ul><li><span style=3D"line-height:normal">not =
RESTful</span></li><li><span style=3D"line-height:normal">adds =
complexity to the callers of the REST API</span></li><li><span =
style=3D"line-height:normal">inconsistent API implementation (mix of =
sync and async)</span></li>

<li><span style=3D"line-height:normal">polling may cause performance =
problems because 1000s of clients are constantly making calls (albeit =
shorter calls)</span></li></ul></div><span><font =
color=3D"#888888"><div><br class=3D"webkit-block-placeholder"></div>

-- <br>
You received this message because you are subscribed to the Google =
Groups "API Craft" group.<br>
To unsubscribe from this group, send email to =
<a>api-craft+...@googlegroups.com</a><wbr>.<br>
Visit this group at <a =
href=3D"http://groups.google.com/group/api-craft?hl=3Den" =
target=3D"_blank">http://groups.google.com/<wbr>group/api-craft?hl=3Den</a=
>.<br>
&nbsp;<br>
&nbsp;<br>
</font></span></blockquote></div><br></div>
</blockquote></div></blockquote></blockquote></div><div><br =
class=3D"webkit-block-placeholder"></div>

-- <br>
You received this message because you are subscribed to the Google =
Groups "API Craft" group.<br>
To unsubscribe from this group, send email to <a =
href=3D"mailto:api-craft+unsubscribe@googlegroups.com">api-craft+unsubscri=
be@googlegroups.com</a>.<br>
Visit this group at <a =
href=3D"http://groups.google.com/group/api-craft?hl=3Den">http://groups.go=
ogle.com/group/api-craft?hl=3Den</a>.<br>
&nbsp;<br>
&nbsp;<br>
</blockquote></div><br></div></body></html>=

--Apple-Mail=_7FFE254E-52F7-44B1-9971-DC3A37AE3D87--