守望者:我缺少订阅前发生的文件删除
watchman: I am missing file deletions happening before subscription
我在守望者中缺少删除。版本 4.9.0,inotify.
我的测试代码:
#!/usr/bin/env python3
import pathlib
import pywatchman
w = pywatchman.client()
w.query('watch', '/tmp/z')
clock = w.query('clock', '/tmp/z')['clock']
print(clock)
q = w.query('subscribe', '/tmp/z', 'Buffy', {'expression':["since", clock],
"fields": ["name", "exists", "oclock", "ctime_ns", "new", "mode"]})
print(q)
f = pathlib.Path('/tmp/z/xx')
f.touch()
data = w.receive()
clock = data['clock']
print()
print('Touch file:')
print(data)
print('Clock:', clock)
f.unlink()
print()
print('Delete file:')
print(w.receive())
w.close()
w = pywatchman.client(timeout=99999)
q = w.query('subscribe', '/tmp/z', 'Buffy', {'expression':["since", clock],
"fields": ["name", "exists", "oclock", "ctime_ns", "new", "mode"]})
print(q)
print()
print('We request changes since', clock)
print(w.receive())
w.close()
我所看到的:
我们创建文件。我们收到新文件和目录更改的通知。 好。我们注意到此通知的"clock"。
我们删除文件。我们收到文件删除的通知。 好。不要收到目录更改的通知。
现在想象一下,进程在更新内部细节之前崩溃了,但它记住了在步骤 1 中通知的更改(目录更新和新文件的创建)。即事务1处理完了,但是事务2还没处理完程序就崩溃了。
我们现在打开一个新的 watchman 订阅(记住,我们正在模拟崩溃)并请求自第 1 步以来的更改。我正在模拟恢复,程序重新启动,注意事务 1 是确定(文件存在)并请求更多更改(应该删除)。
我希望删除文件,但我...什么都没有。 灾难性的.
成绩单:
$ ./watchman-bug.py
c:1517109517:10868:3:23
{'clock': 'c:1517109517:10868:3:23', 'subscribe': 'Buffy', 'version': '4.9.0'}
Touch file:
{'unilateral': True, 'subscription': 'Buffy', 'root': '/tmp/z', 'files': [{'name': 'xx', 'exists': True, 'oclock': 'c:1517109517:10868:3:24', 'ctime_ns': 1517114230070245747, 'new': True, 'mode': 33188}], 'is_fresh_instance': False, 'version': '4.9.0', 'since': 'c:1517109517:10868:3:23', 'clock': 'c:1517109517:10868:3:24'}
Clock: c:1517109517:10868:3:24
Delete file:
{'unilateral': True, 'subscription': 'Buffy', 'root': '/tmp/z', 'files': [{'name': 'xx', 'exists': False, 'oclock': 'c:1517109517:10868:3:25', 'ctime_ns': 1517114230070245747, 'new': False, 'mode': 33188}], 'is_fresh_instance': False, 'version': '4.9.0', 'since': 'c:1517109517:10868:3:24', 'clock': 'c:1517109517:10868:3:25'}
{'clock': 'c:1517109517:10868:3:25', 'subscribe': 'Buffy', 'version': '4.9.0'}
We request changes since c:1517109517:10868:3:24
进程挂起等待删除通知。
我做错了什么?
感谢您的时间和知识!
问题是您使用的是 since
表达式术语,而不是通知 watchman 使用 since
生成器(新近度指数)。
有什么区别?您可以将此视为 SQL 中 FROM
和 WHERE
子句之间的区别。 expression
字段在意图上与 WHERE
子句类似:它适用于匹配的结果并将它们过滤掉,但您想要做的是通过设置 FROM
子句来指定 since
查询规范中的字段。诚然,这是一个细微的差别。
解决方案是删除表达式项并添加生成器项,如下所示:
q = w.query('subscribe', '/tmp/z', 'Buffy',
{"since": clock,
"fields": ["name", "exists", "oclock",
"ctime_ns", "new", "mode"]})
虽然我们确实没有任何关于使用 pywatchman API 的文档,但您可以从文档稍微好一点的 nodejs API 中借用这些概念;这是一个相关的片段:
https://facebook.github.io/watchman/docs/nodejs.html#subscribing-only-to-changed-files
我在守望者中缺少删除。版本 4.9.0,inotify.
我的测试代码:
#!/usr/bin/env python3
import pathlib
import pywatchman
w = pywatchman.client()
w.query('watch', '/tmp/z')
clock = w.query('clock', '/tmp/z')['clock']
print(clock)
q = w.query('subscribe', '/tmp/z', 'Buffy', {'expression':["since", clock],
"fields": ["name", "exists", "oclock", "ctime_ns", "new", "mode"]})
print(q)
f = pathlib.Path('/tmp/z/xx')
f.touch()
data = w.receive()
clock = data['clock']
print()
print('Touch file:')
print(data)
print('Clock:', clock)
f.unlink()
print()
print('Delete file:')
print(w.receive())
w.close()
w = pywatchman.client(timeout=99999)
q = w.query('subscribe', '/tmp/z', 'Buffy', {'expression':["since", clock],
"fields": ["name", "exists", "oclock", "ctime_ns", "new", "mode"]})
print(q)
print()
print('We request changes since', clock)
print(w.receive())
w.close()
我所看到的:
我们创建文件。我们收到新文件和目录更改的通知。 好。我们注意到此通知的"clock"。
我们删除文件。我们收到文件删除的通知。 好。不要收到目录更改的通知。
现在想象一下,进程在更新内部细节之前崩溃了,但它记住了在步骤 1 中通知的更改(目录更新和新文件的创建)。即事务1处理完了,但是事务2还没处理完程序就崩溃了。
我们现在打开一个新的 watchman 订阅(记住,我们正在模拟崩溃)并请求自第 1 步以来的更改。我正在模拟恢复,程序重新启动,注意事务 1 是确定(文件存在)并请求更多更改(应该删除)。
我希望删除文件,但我...什么都没有。 灾难性的.
成绩单:
$ ./watchman-bug.py
c:1517109517:10868:3:23
{'clock': 'c:1517109517:10868:3:23', 'subscribe': 'Buffy', 'version': '4.9.0'}
Touch file:
{'unilateral': True, 'subscription': 'Buffy', 'root': '/tmp/z', 'files': [{'name': 'xx', 'exists': True, 'oclock': 'c:1517109517:10868:3:24', 'ctime_ns': 1517114230070245747, 'new': True, 'mode': 33188}], 'is_fresh_instance': False, 'version': '4.9.0', 'since': 'c:1517109517:10868:3:23', 'clock': 'c:1517109517:10868:3:24'}
Clock: c:1517109517:10868:3:24
Delete file:
{'unilateral': True, 'subscription': 'Buffy', 'root': '/tmp/z', 'files': [{'name': 'xx', 'exists': False, 'oclock': 'c:1517109517:10868:3:25', 'ctime_ns': 1517114230070245747, 'new': False, 'mode': 33188}], 'is_fresh_instance': False, 'version': '4.9.0', 'since': 'c:1517109517:10868:3:24', 'clock': 'c:1517109517:10868:3:25'}
{'clock': 'c:1517109517:10868:3:25', 'subscribe': 'Buffy', 'version': '4.9.0'}
We request changes since c:1517109517:10868:3:24
进程挂起等待删除通知。
我做错了什么?
感谢您的时间和知识!
问题是您使用的是 since
表达式术语,而不是通知 watchman 使用 since
生成器(新近度指数)。
有什么区别?您可以将此视为 SQL 中 FROM
和 WHERE
子句之间的区别。 expression
字段在意图上与 WHERE
子句类似:它适用于匹配的结果并将它们过滤掉,但您想要做的是通过设置 FROM
子句来指定 since
查询规范中的字段。诚然,这是一个细微的差别。
解决方案是删除表达式项并添加生成器项,如下所示:
q = w.query('subscribe', '/tmp/z', 'Buffy',
{"since": clock,
"fields": ["name", "exists", "oclock",
"ctime_ns", "new", "mode"]})
虽然我们确实没有任何关于使用 pywatchman API 的文档,但您可以从文档稍微好一点的 nodejs API 中借用这些概念;这是一个相关的片段:
https://facebook.github.io/watchman/docs/nodejs.html#subscribing-only-to-changed-files