Mercurial > templog
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() + + + + +