【问题标题】:How to implement watcher for descendant items?如何实现后代项目的观察者?
【发布时间】:2021-07-04 10:13:41
【问题描述】:

上下文

# Every mapping has a parent whose path is a prefix with one less element; the exception to this rule is root ("/") which has no parent.
# Unlike a regular file system, all these mappings can have both data (so it acts like a file) and children (so it acts like a directory)

# The data structure used is a dictionary called store. Values are arbitrary, by default there is an initial key of "/".  
# All keys start with the absolute path, for example "/dir1/file1".  
# Its not able to create a key if its parent key does not exist. 
# For example, it cannot create "/app1/p1" if dictionary only has the "/" key. It has to create an "/app1" key first, then call create on "/app1/p1"  

#                         (tree visualization example)
#                                    "/"  
#                      /                             \
#                  "/app1"                        "/app2" ...
#     /            /         \
# "/app1/p1"  "/app1/p2" "/app1/p3" ... 


class Zookeeper():
    store = {"/":None}
    def create(self, path, value):
        if self.validate(path):
            self.store[path] = value
        else:
            pass
            #raise KeyError("create error: {} invalid".format(path))
    
    def read(self, path):
        if path in self.store.keys():
            return self.store[path]
        else:
            return "read error: {} does not exist".format(path)
    
    def update(self, path, value):
        if path in self.store.keys():
            self.store[path] = value
        else:
            return "update error: {} does not exist".format(path)

    def validate(self, path):
        if path is None:
            return False
        if len(path.strip()) == 0:
            return False
        if path[0] != "/":
            return False
        if path.rindex("/") == path.index("/"):
            return True
        if path[0:path.rindex("/")] not in self.store:
            return False
        if path in self.store:
            return False
        return True


zk = Zookeeper()
zk.create("/app1", "/app1 value")
print(zk.read("/app1"))

zk.create("/app1/p1", "/app1/p1 value")
print(zk.read("/app1/p1"))

zk.create("/p1/p1", "/p1/p1 value")
print(zk.read("/p1/p1"))

zk.create("/p1", "/p1 value")
print(zk.read("/p1"))

zk.create("/p1/p1", "/p1/p1 value")
print(zk.read("/p1/p1"))

更多上下文
问题是实现一个watch方法

watch(path, watcher)  
  • 设置一个观察者,只要被观察的路径或其任何后代通过调用 update 或 create 进行更新,就会调用该观察者
  • watch 接受路径和某种侦听器对象(取决于语言,它可以是函数、指针、对象或其他东西)
  • 无论何时设置 path 或其任何后代的值,都必须调用为该路径注册的回调
  • 观察者应该接受两个参数 - 更改的路径和设置的值

你是如何实现watch的?

【问题讨论】:

    标签: algorithm dictionary watch key-value-store descendant


    【解决方案1】:

    您的路径都被实现为平面字典中的字符串这一事实简化了一些事情,并使其他事情复杂化。

    如果在安装观察程序时,您只想查看路径的该级别,而不是子级别,那么它非常简单。

    由于所有访问都是通过“创建”或“更新”方法进行的,因此您所要做的就是检查这些方法是否存在正在修改的路径的“观察者”。观察者注册表可以是一个简单的字典,就像“.store”一样 - 您甚至可以通过将商店的值设置为序列来为每个键设置多个侦听器。

    “监视”功能甚至可以在您原始类的子类中轻松实现:

    
    class WatchableZookeeper():
        def __init__(self):
            self.listeners = {}
            super().__init__()
            
    
        def watch(self, path, listener):
            # The "setdefault" method in dictionaries will create a new emty
            # list as the value, if it does not exist, and return it - 
            # otherwise it returns the existing list:
            self.listeners.setdefault(path, []).append(listener)
        
        def update(self, path, value):
            # let the superclass update run first: 
            # if it raises an error, we let it bubble up nd do not call the events!
            super().update(path, value)
            for listener in self.listeners.get(path):
                listerner(path, value)
                
        def create(self, path, value):
            super().update(path, value)
            for listener in self.listeners.get(path):
                listerner(path, value)
                
    

    【讨论】:

      猜你喜欢
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-21
      • 1970-01-01
      相关资源
      最近更新 更多