Try and Catch

Can someone explain how how “try” and “catch” works in groovy? My app, which pings a remote server, sometimes fails when the server does not respond within a certain timeframe. This failure is not all too serious as long as the app recovers from this error. My app does not. After an error such as “Exception occurred: java.util.concurrent.TimeoutExce…” the app stops. The code looks something like this:

def pingServer() { // called every 4 hours or what ever was defined in prefs
runNotifyAt(now() + state.pingInterval) // Queue the next time this function is called; in 4 hours
try {
httpGet(“http://url:port:/ping.php”) {response ->
// do something with data…
}
} catch(e)
{
sendNotificationEvent(“Exception occurred: $e”)
}

Even though the next run (in 4 hours) has been queued before an exception error occured this scheduled job disappears in such case. How do I prevent the app from terminating when such error occurs??

I don’t think you can. This is the 20 second timeout failure, that is known to kill apps with schedules, such as Pollster. ST figures that the app is bad, so kills it’s scheduled jobs along with it. AFAIK, the only way to get it going again is manually.

1 Like

It’s supposed to work as you are using it…

try {
  // some stuff
}
catch (e)
{
  // what you do if an exception is thrown in the try part
}
// life goes on either way

You’re following the right pattern http://docs.smartthings.com/en/latest/smartapp-developers-guide/calling-web-services-in-smartapps.html

1 Like

[quote=“bravenel, post:2, topic:33751”]
This is the 20 second timeout failure, that is known to kill apps with schedules, such as Pollster.
[/quote]I don’t think it is, since the httpGet should time out after 10 seconds.

1 Like

Well that pretty much sums up what happens to my app.

For 2 years I have been struggling with this Wifi module installed in my hot tub. The thing falls off the network like clockwork. Only way to recover is to reboot the entire tub. This issue is well know to both the company who installed it and all us unfortunates who own one. But hooray… I found a solution. removed the module and hooked up an inline z-wave relay switch to it. If the module falls off the wifi, toggle the relay switch (off then on) and voila… back online. To automate this, I wrote this app. If the ping returns “inactive” I toggle the relay. Now I find that if the app fails I need to restart it manually… :anguished: Arrrrrggghhhhhh I cant win…

Some guys are using Rule Machine for something like this, have a rule that checks that something happened, and if not, making it happen. Not sure if that would work, but… Sort of a bandaid approach (like try-catch isn’t!).

@Ben or anyone in documentation land… is there a parm for connection timeout and/or socket timeout?

In normal java/groovy you would do some variant of setting either of them

  builder.getClient().getParams().setParameter("http.connection.timeout", 1000)
  builder.getClient().getParams().setParameter("http.socket.timeout", 1000)

It’s not documented if there are params to httpGet for either. I assume if there are setting them lower (say 1 second) should be sufficient to have the httpGet timeout before the overall smartApp timeout kicks in.

Alternately (puts on armor) perhaps the platform should not count tcp wait times in overall execution time for purposes of killing long running smart apps? After all, it’s not actually doing anything when it’s blocking in an iowait…

Or, the default timeout for http requests should be shortened so running until an iotimeout on a get doesn’t get your smartapp killed?

2 Likes

I was just messing around with a rule to gradually dim a light, and by pure luck the first time it was scheduled to change the dimmer level was at 9:00:07. Guess what? I got the dreaded

error java.util.concurrent.TimeoutException: Execution time exceeded 20 app execution seconds: 57834689356351

Just shows that peak times are real!! The future scheduled job was killed, or never got scheduled. Restarted the app 2 minutes later, and now it’s running fine, as in, once a minute dimming the light.

Notice the execution time at 9:00:07

1 Like

I don’t even mind that at times a timeout error occurs. This app is hardly critical. If my Spa is not reachable I can manually toggle the relay switch via the ST app. But that is not the real issue… I want the app to continue running after such error occurs. That it halts and deletes all future scheduled jobs is very annoying.

You should submit a ticket on this, and I will also. It’s one thing for them to kill an app for running over 20 seconds, but when the 20 seconds is caused by them having it stuck in a queue during a peak time is simply insulting.

5 Likes

Good idea. Will do…

What’s the logic you’re using to schedule the job periodically?

It was simply delaying for 1 minute and then turning on a momentary button (using runIn()). The momentary button on event was a trigger to run again.

Ah yeah - those “set to run after X” when inside an event methods can go poof if the app is killed by the platform.

Off topic but maybe this will work for your problem: I have a Wifi Airplay receiver that failed and disconnected after ~48 hours. I use a cheap mechanical timer (~$2.50) to switch it on/off every day during a time when I am sure I will not use it (e.g. 2:30-3am in the morning). That daily refresh fixed the problem and Wifi connection is now reliable.

bad attitude. It’s FUNNY!

I can speak to the connection timeout - there is no way to set the timeouts for any of the http* methods. They are hard-coded to 10 seconds.

Also just an FYI, it looks like the sandbox timeout is reset after the request completes, but before passing control back to the caller’s closure that processes the response. This means that if, for example, you have a method that has been executing for 2 seconds, then make an HTTP request and it takes 8 seconds, when control is returned to your SmartApp the method execution timer is reset to zero.