跳至主要内容

subscribe

自 1.6 版本起

订阅指定根目录的更改,并请求通过连接将其发送到客户端。 更新将继续发送,直到连接打开。 如果连接关闭,则订阅将隐式删除。

这在通过套接字接口连接的应用程序中最有意义,但如果您有兴趣自己观察更改,您也可以通过命令行工具进行订阅

$ watchman -j --server-encoding=json -p <<-EOT
["subscribe", "/path/to/root", "mysubscriptionname", {
"expression": ["allof",
["type", "f"],
["not", "empty"],
["suffix", "php"]
],
"fields": ["name"]
}]
EOT

上面的示例使用名称 mysubscriptionname 针对指定的根目录注册订阅。

对 subscribe 命令的响应如下所示

{
"version": "1.6",
"subscribe": "mysubscriptionname"
}

首次建立订阅时,将评估表达式项,如果任何文件匹配,则会生成订阅通知数据包并单方面发送到客户端。

然后,每次观察到更改并在稳定期过去后,将再次评估表达式。 如果任何文件匹配,服务器会将查询结果以如下所示的数据包单方面发送到客户端

{
"version": "1.6",
"clock": "c:1234:123",
"files": ["one.php"],
"root": "/path/being/watched",
"subscription": "mysubscriptionname"
}

subscribe 命令对象允许客户端指定 since 参数; 如果命令中存在该参数,则初始的订阅结果集将仅包含自指定 clockspec 以来已更改的文件,相当于使用带有 since 生成器的 query 命令。

["subscribe", "/path/to/root", "myname", {
"since": "c:1234:123",
"expression": ["not", "empty"],
"fields": ["name"]
}]

建议的操作模式是客户端进程维护其自己的最后一个“clock”值的本地副本,并在首次连接时使用该值来建立订阅。

文件系统稳定

在 watchman 3.2 版本之前,稳定行为是保持订阅通知,直到内核通知流完成。

从 watchman 3.2 版本开始,在通知流完成后,如果根目录似乎是版本控制目录,则订阅通知将保持,直到未完成的版本控制操作完成(在撰写本文时,这基于是否存在 .hg/wlock.git/index.lock)。 此行为与触发器匹配,有助于避免响应文件更改而执行临时工作,例如,在 rebase 操作期间。

在某些情况下,客户端希望在版本控制操作开始时观察控制文件的创建。 您可以通过将 defer_vcs 标志传递给您的订阅命令调用来指定您希望此行为

$ watchman -j -p <<-EOT
["subscribe", "/path/to/root", "mysubscriptionname", {
"expression": ["allof",
["type", "f"],
["not", "empty"],
["suffix", "php"]
],
"defer_vcs": false,
"fields": ["name"]
}]
EOT

高级稳定

自 4.4 版本起

在更复杂的集成中,希望能够让 watchman 感知的应用程序发出某些工作的开始和结束信号,这些工作将生成大量更改通知。 例如,Mercurial 或 Git 可以在更新工作副本之前和之后与 watchman 通信。

有些应用程序希望知道更新正在进行中并继续处理通知。 其他应用程序可能希望推迟处理通知,直到更新完成,而有些应用程序可能希望删除更新进行时产生的任何通知。

Watchman 订阅为每个这些用例提供机制,并通过订阅对象中的两个新字段公开它; 下面介绍了 deferdrop

在给定订阅流的上下文中,在多个重叠状态下混合使用 deferdrop 可能很困难,因为只有一个游标来跟踪订阅位置。

如果您的应用程序使用多个重叠状态并且想要 defer 某些结果并 drop 其他结果,建议您对所有状态使用 drop,然后发出带有受订阅状态 PDU 中的 clock 字段限制的 since 项的查询,以确保它观察到所有感兴趣的结果。

defer

["subscribe", "/path/to/root", "mysubscriptionname", {
"defer": ["mystatename"],
"fields": ["name"]
}]

defer 字段指定订阅者希望推迟通知流的状态名称列表。 当 watchman 客户端通过 state-enter 命令发出已进入状态的信号时,如果状态名称与 defer 列表中的任何状态名称匹配,则订阅将发出如下所示的单方面订阅 PDU

{
"subscription": "mysubscriptionname",
"root": "/path/to/root",
"state-enter": "mystatename",
"clock": "<clock>",
"metadata": <metadata from the state-enter command>
}

然后,Watchman 将推迟发送任何带有 files 有效负载的订阅 PDU,直到该状态通过 state-leave 命令或通过进入该状态的客户端断开与 watchman 服务的连接而空置为止。

状态被空置后,watchman 将发出如下所示的单方面订阅 PDU

{
"subscription": "mysubscriptionname",
"root": "/path/to/root",
"state-leave": "mystatename",
"clock": "<clock>",
"metadata": <metadata from the exit-state command>
}

然后将重新启用订阅流,并且自相应的 state-enter 以来收到的通知将被传递给客户端。

drop

["subscribe", "/path/to/root", "mysubscriptionname", {
"drop": ["mystatename"],
"fields": ["name"]
}]

drop 字段指定订阅者希望丢弃通知流的状态名称列表。 它的工作方式与上面描述的 defer 非常相似,但是当状态被空置时,挂起的通知流将快进到 state-leave 命令的时钟,从而有效地抑制了在 state-enterstate-leave 命令之间生成的任何通知。

源代码控制感知订阅

自 4.9 版本起

在此处阅读更多相关信息