class Reader(QonPersistent): """Represents a single user/reader of a Blog. Uses a conflict-avoiding IO BTree: self.read_items[item_id] = (datetime, count) """ persistenceVersion = 2 def __init__(self, user): self.user = user self.read_items = ConflictAvoidingIOBTree() def upgradeToVersion2(self): for k,v in self.read_items.iteritems(): self.read_items[k] = (v, 0) self.version_upgrade_done() def upgradeToVersion1(self): newbt = ConflictAvoidingIOBTree() for k,v in self.read_items.iteritems(): newbt[k] = v del self.read_items self.read_items = newbt self.version_upgrade_done() def read_item(self, item_id, now=None): """Notice that I have read item number item_id. Returns self as a convenience.""" now = now or datetime.utcnow() dt, count = self.read_items.get(item_id, (never, 0)) # don't allow changing last_read to anything earlier than it is now now = max(now, dt) self.read_items[item_id] = (now, count + 1) return self def has_read_item(self, item_id, updated=None): """Have I read item_id, which was optionally updated at updated?""" last_read, count = self.read_items.get(item_id, (None, 0)) if last_read: if updated: return last_read >= updated else: return True return False def last_read(self, item_id): """Return the datetime of the last time that the user read a BlogItem""" dt, count = self.read_items.get(item_id, (never, 0)) return dt def last_read_count(self, item_id): """Return (last read datetime, count int).""" return self.read_items.get(item_id, (never, 0))
def __init__(self, user): self.user = user self.read_items = ConflictAvoidingIOBTree()