Be less spammy when SpaceAPI update fails
[saartuer.git] / spaceapi.py
1 from threading import Lock
2 from libtuer import ThreadFunction, logger
3 import urllib.request, time
4
5 from config import spaceApiKey
6
7 RETRY_TIME = 60
8 HEARTBEAT_TIME = 10*60
9
10 class SpaceApi:
11         def __init__ (self, waker):
12                 self._local_state = None
13                 self._remote_state = None
14                 self._last_set_at = 0
15                 self._running = True
16                 self._fail_count = 0 # number of consecutive fails
17                 self.set_state = ThreadFunction(self._set_state, "Space API")
18                 waker.register(self.set_state, RETRY_TIME)
19         
20         def stop (self):
21                 self.set_state.stop()
22         
23         def _do_request(self, state):
24                 state_val = 1 if state else 0
25                 try:
26                         logger.info("Setting SpaceAPI to %d" % state_val)
27                         url = "https://spaceapi.hacksaar.de/status.php?action=update&key=%s&status=%d" % (spaceApiKey, state_val)
28                         response = urllib.request.urlopen(url, timeout=5.0)
29                         responseText = response.read().decode('utf-8').strip()
30                         if response.getcode() == 200 and responseText == "UpdateSuccessful": return True
31                         logger.error("SpaceAPI returned unexpected code %d, content %s" % (response.getcode(), responseText))
32                         return False
33                 except urllib.request.URLError as e:
34                         logger.error("SpaceAPI update returned error: %s" % str(e))
35                         return False
36         
37         # set_state is the asynchronous version of _set_state (see __init__)
38         def _set_state (self, state = None):
39                 '''Sets the state, if None: leave state unchanged and re-try if previous attempts failed'''
40                 if state is not None:
41                         self._local_state = state
42                 # check if there's something we need to do: There's a valid state, and either the state has changed or
43                 # we need to refresh our heartbeta)
44                 now = time.time()
45                 if self._local_state is not None and (self._local_state != self._remote_state or now > self._last_set_at+HEARTBEAT_TIME):
46                         # take action!
47                         success = self._do_request(self._local_state)
48                         if success:
49                                 self._remote_state = self._local_state
50                                 self._last_set_at = now
51                                 self._fail_count = 0
52                         else:
53                                 self._fail_count += 1
54                                 if self._fail_count in (5, 100):
55                                         logger.critical("Updating the SpaceAPI failed %d times in a row" % self._fail_count)