fix: don't close client sockets too early
[saartuer.git] / spaceapi.py
index 89e3678290e652773306d697aa642a364b2c1e55..181981ada949494c91e97ce9f22d5dafd1d32b71 100644 (file)
@@ -1,17 +1,21 @@
 from threading import Lock
 from libtuer import ThreadFunction, logger
-import urllib.request
+import urllib.request, time
 
 from config import spaceApiKey
 
+RETRY_TIME = 60
+HEARTBEAT_TIME = 10*60
+
 class SpaceApi:
        def __init__ (self, waker):
-               self._state_to_set = None
-               self._state_last_set = None
+               self._local_state = None
+               self._remote_state = None
+               self._last_set_at = 0
                self._running = True
+               self._fail_count = 0 # number of consecutive fails
                self.set_state = ThreadFunction(self._set_state, "Space API")
-               self._set_state_lock = Lock()
-               waker.register(self.set_state, 10.0) # re-try setting the state every 10 seconds
+               waker.register(self.set_state, RETRY_TIME)
        
        def stop (self):
                self.set_state.stop()
@@ -20,7 +24,7 @@ class SpaceApi:
                state_val = 1 if state else 0
                try:
                        logger.info("Setting SpaceAPI to %d" % state_val)
-                       url = "http://spaceapi.hacksaar.de/status.php?action=update&key=%s&status=%d" % (spaceApiKey, state_val)
+                       url = "https://spaceapi.hacksaar.de/status.php?action=update&key=%s&status=%d" % (spaceApiKey, state_val)
                        response = urllib.request.urlopen(url, timeout=5.0)
                        responseText = response.read().decode('utf-8').strip()
                        if response.getcode() == 200 and responseText == "UpdateSuccessful": return True
@@ -34,24 +38,18 @@ class SpaceApi:
        def _set_state (self, state = None):
                '''Sets the state, if None: leave state unchanged and re-try if previous attempts failed'''
                if state is not None:
-                       self._state_to_set = state
-               else:
-                       # always have a local variable because of parallelism
-                       state = self._state_to_set
-               
-               if not self._set_state_lock.acquire(False):
-                       # we don't want many threads to wait here
-                       # the next status update will fix everything anyways
-                       pass
-               else:
-                       # got the lock
-                       try:
-                               # check if there's something we need to do
-                               if self._state_last_set == state: return
-                               # take action!
-                               success = self._do_request(state)
-                               # TODO error too often -> log critical to send mails
-                               if success:
-                                       self._state_last_set = state
-                       finally:
-                               self._set_state_lock.release()
+                       self._local_state = state
+               # check if there's something we need to do: There's a valid state, and either the state has changed or
+               # we need to refresh our heartbeta)
+               now = time.time()
+               if self._local_state is not None and (self._local_state != self._remote_state or now > self._last_set_at+HEARTBEAT_TIME):
+                       # take action!
+                       success = self._do_request(self._local_state)
+                       if success:
+                               self._remote_state = self._local_state
+                               self._last_set_at = now
+                               self._fail_count = 0
+                       else:
+                               self._fail_count += 1
+                               if self._fail_count in (5, 100):
+                                       logger.critical("Updating the SpaceAPI failed %d times in a row" % self._fail_count)