diff web/settings.py @ 253:0a1b642e3086

long polling config updates
author Matt Johnston <matt@ucc.asn.au>
date Mon, 08 Jun 2015 22:29:46 +0800
parents
children 03e540c3ec24
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/settings.py	Mon Jun 08 22:29:46 2015 +0800
@@ -0,0 +1,61 @@
+import gevent
+import fcntl
+import hashlib
+
+class Settings(object):
+    RAND_SIZE = 15 # 120 bits
+
+    """ Handles state updates from both the web UI and from the fridge client.
+    The fridge client is canonical. It provides the epoch (apart from 'startepoch'), that
+    is changed any time the fridge reloads its local config. The fridge only accepts
+    updates that have the same epoch.
+
+    When the web UI changes it keeps the same epoch but generates a new tag. The fridge sends
+    its current known tag and waits for it to change.
+
+    content is opaque, presently a dictionary of decoded json 
+    """
+
+    def __init__(self):
+        self.event = gevent.event.Event()
+        self.contents = None
+        self.epoch = None
+        self.tag = None
+
+        self.update(self, None, 'startepoch')
+
+    def wait(self, epoch_tag = None, timeout = None):
+        """ returns false if the timeout was hit """
+        if self.epoch_tag() != epoch_tag:
+            # has alredy changed
+            return True
+        return self.event.wait(timeout)
+
+    def epoch_tag(self):
+        return '%s-%s' % (self.epoch, self.tag)
+
+    def random(self):
+        return binascii.hexlify(os.urandom(self.RAND_SIZE))
+
+    def update(self, contents, epoch = None):
+        """ replaces settings contents and updates waiters if changed """
+        if epoch:
+            if self.epoch == epoch:
+                return
+            else:
+                self.epoch = epoch
+
+        self.tag = self.random()
+        self.contents = contents
+
+        self.event.set()
+        self.event.clear()
+
+    def get(self):
+        """ Returns (contents, epoch-tag) """
+        return self.contents, self.epoch_tag()
+
+
+
+
+