Asynchronous HTTP API - Beta Launch

Originally published at: http://devblog.smartthings.com/2016/10/17/asynchronous-http-api-beta-launch/

SmartThings Developers - we’re excited to announce a beta version of APIs that allow developers to make HTTP requests to third party services asynchronously.

These APIs work similarly to existing APIs like httpGet(), httpPut(), etc., but with one big difference - they are executed asynchronously. Here’s an example of making an asynchronous GET request:

include ‘asynchttp_v1’

def initialize() {
    def params = [
        uri: “https://api.github.com”,
        path: “/search/code”,
              query: [q:‘httpGet+repo:SmartThingsCommunity/SmartThingsPublic’]
    ]
    // make request, passing the name of the method to call
    // with the response
    asynchttp_v1.get(“responseHandler”, params)
}

// response handler is called when the request completes
// (in another execution of the SmartApp or Device Handler)
def responseHandler(response, data) {
    def total = response.json.total_count
    log.debug “there are $total occurrences of httpGet”
}

The difference between synchronous and asynchronous HTTP APIs is best illustrated by the following diagrams:

Below: synchronous HTTP requests wait for the response within a single execution

Below: asynchronous requests receive the response in a separate execution

Due to its asynchronous nature, requests made with the new asynchronous APIs are less likely to encounter timeouts from long running requests or response processing. The response object returned by the new asynchronous APIs is also easier to work with, in our opinion.

The new asynchronous HTTP APIs are available to both SmartApps and Device Handlers. The documentation can be found here.

We are releasing these APIs as beta so that we can evaluate usage, tune as necessary, and collect feedback from you. There’s no special sign-up for these APIs, they are available to everyone.

Let us know if you have any questions that aren’t covered here or in the documentation. Happy coding!

14 Likes

This is great Tim. Looks like it supports https also.
2 questions:

  1. Is ST also planning to extend this to the hubAction or some form of local/private addressing mechanism?
  2. How does the platform performance impact this v/s a synchronous call. I.e. When the planning is running slow the synchronous call (esp when called often) times out, in such a scenario how would this asynchronous call differ? Also if it does timeout would it let the SA/DH know through the response handler?

Not in a short amount of time.

In almost all cases a-sync is less stressful on the platform. It is the difference between an app running the entire time a call is being made vs. a call being made then the app shutting down and is spun back up when the call returns.

The documentation spells out how to get errors from the response if there are any. :slight_smile:

3 Likes

@slagle Tim, obviously this is being done to free up threads on the backend infrastructure. To me, this could be huge for performance. Are you guys privately really, really excited at the possible stability improvements once the highest-usage smartapps implement async? Or are the number of calls (currently synchronous) being made to external services a small part of backend performance?

In other words, give us some hope this might significantly improve performance across the backend, or temper our (my) expectations :).

Thx.

2 Likes

It’s one head of a medusa. We are publically excited about the stability improvements but know a) it won’t solve everything and b) developers need to start updating their SmartApps to reflect the changes.

Feel free to post feedback here: Asynchronous HTTP Beta Feedback Thread (since this both a beta and dev feature, I kindly request you not email support@ with async bugs, feedback, etc)

This is good stuff - nice job guys. I’ve written a SmartApp using the async model with HubAction, but this looks much more fleshed out (particularly the ability to send data in the request that passes through to the response). Definitely looking forward to seeing this model applied to the hubAction LAN calls someday.

Medusa only had one head, but hair of snakes. You may be thinking of the Hydra which has a varied number of heads, that each when cut off, regrow in single or multiple replacements. Pretty apt metaphor, really.

This enhancement is exciting.

Now for more local execution please.

I stand corrected and humbly submit:

4 Likes

This is great! I have an async web services app that’s i’m close to finishing and now I’ll have async HTTP API from SmartThings to pair together!

Kudos on this guys! Soon as I get a chance, I’ll try to give it a whirl.

2 Likes

Hail Hydra!

Please forgive my ignorance as I’m relatively new to Smartthings. Could give me a real world example where this would be useful? I haven’t encountered any timeouts or issues connecting to third party services yet, but admittedly I am relatively new to using smartthings. As a software performance engineer in my day job, I was just curious. We use async architectures to solve performance issues all the time, but I just haven’t encountered any problems so far with Smartthings integration yet that I can see a real world example that this would help solve. I’m sure they exist, but was just curious.

@johnwest80

To follow up on Aaron’s post.

The fact is this won’t really do much to enhance back end performance. Maybe a little bit because the app isn’t running in the sandbox for the entire http call. What it does do is allow http calls that take a long time to not hit the app execution time. (There are some REALLY slow APIs out there… we see some calls taking as long as 60 seconds to return to us… And that’s more common than you might think… some of them are APIs you’d expect to be fast APIs too.)

1 Like

First, in general if your request doesn’t have to be synchronous you should make it asynchronous so it doesn’t block other things within the same thread from happening.

A real world example is when Amazon takes your order, they asynchronously charge your credit card but tell you that your order has been successfully submitted before they even know if they can bill you. This is because they want NOTHING preventing an order from taking place, even if your are over your limit or something. They then follow up and say “hey, you need to give us another credit card”.

DH Example - Not the best example…
I have a device handler called LIFX Group of Groups which allows you to treat a group of LIFX bulbs as a single device. Using their API I can tell the lights to turn on, off, set level, set color, … When I tell the device to turn on to get the lights to turn on as quickly as possible, the first thing I do is tell LIFX cloud to turn on the lights, then I update the DH to show the lights have turned on, but this is what it looks like…

1 - Tell LIFX to turn the lights on.
2 - Wait for LIFX to respond.
3 - Tell the ST UI the light is on.

Seems simple, but step 3 might end up taking 500ms to 3-4 seconds to get to. I don’t just do step #3 first as I want the actual call to turn the light on to happen as fast as possible.

With Asynchronous I can…

1 - Tell LIFX to turn on the lights.
2 - Tell the ST UI the light is on (even if it isn’t, because 99.5% of the time the light does turn on).
3 - Wakeup when LIFX responses success or failure and then update the ST UI if the event failed to show the light is actually not on.

Another way to do this would have been to do a

runIn(0, sendOnToLIFX) or something like that but the asynchronous call is much cleaner.

5 Likes

Any news on the progress of this?

How did it go?

And does this mean that someone can probably resurrect the TCP Connected bulbs by doing some crazy HTTP calls to the TCP hub which now only listens to local commands from the LAN? :slight_smile:

1 Like