New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
10.0 dev reload with inotify #31855
10.0 dev reload with inotify #31855
Conversation
Python2 uses IOError instead. /!\ DO NOT FORWARD PORT AFTER 11.* /!\
Before this commit every worker would start his own FSWatcher.
odoo/service/server.py
Outdated
if 'reload' in config['dev_mode']: | ||
if watchdog: | ||
if 'reload' in config['dev_mode'] and not odoo.evented: | ||
if inotify and not odoo.evented: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check on odoo.evented
is useless (already checked the line before)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whoops, indeed
odoo/service/server.py
Outdated
if not self.watcher: | ||
self.watcher = InotifyTree(path, mask=INOTIFY_LISTEN_EVENTS, block_duration_s=1.0) | ||
else: | ||
self.watcher._InotifyTree__load_tree(path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ho yes, it's dirty
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, But this avoids having to iterate through different InotifyTree and have all the events on a single fd, which, on my 500 addons-paths test prevents a constant 2% CPU usage to iterate on every path every second.
odoo/service/server.py
Outdated
while self.started: | ||
for event in self.watcher.event_gen(timeout_s=0, yield_nones=False): | ||
(_, type_names, path, filename) = event | ||
if filename.endswith('.py') and not filename.startswith('.~') and 'IN_ISDIR' not in type_names: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you extract this block inside a common function with FSWatcher
using a common ancestor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do
odoo/service/server.py
Outdated
if os.name == 'posix': | ||
module = 'inotify' | ||
else: | ||
module = 'Watchdog' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lowercase
odoo/service/server.py
Outdated
watcher = FSWatcher() | ||
watcher.start() | ||
else: | ||
_logger.warning("'watchdog' module not installed. Code autoreload feature is disabled") | ||
if os.name == 'posix': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is not inotify
on osx. watchdog is still needed
18b4645
to
4fc2b60
Compare
@KangOl @antonylesuisse
a) Do we automatically reload upon directory moves?
Is this intended behaviour? Current inotify implementation copies this. It doesn't listen to
|
On 15 Mar 2019, at 12:47, Denis Vermylen wrote:
@KangOl @antonylesuisse
The `FSWatcherInotify` runs fine for the expected scenarios, but a few questions remain:
1) Inotify behaves a bit differently when moving folders containing files than watchdog. Watchdog will give the notifications for each file in the folder, while inotify only gives the folder move event (I believe because the files get created before inotify gets a chance to add the folder to its watchlist, not sure how watchdog handles this). The question becomes:
a) Do we automatically reload upon directory moves?
b) Do we os.walk the directory in search of python files and reload only if it contains one & it compiles?
c) Do we ignore them? <-- current implementation
It's better to have the same behaviour with both packages. I would go with b) then.
2) Current watchdog implementation ignores when we delete or move a file away from the folder, even a python file.
Is this intended behaviour? Current inotify implementation copies this. It doesn't listen to `IN_DELETE, IN_DELETE_SELF, IN_MOVE_SELF, IN_MOVED_FROM` events. ( http://man7.org/linux/man-pages/man7/inotify.7.html )
You choose. You can keep current status or implement it.
3) Is it ok to use the `__load_tree` method from the `InotifyTree` object? Its signature hasn't changed since its addition 4 years ago. https://github.com/dsoprea/PyInotify/blame/master/inotify/adapters.py#L342
There is actually InotifyTrees (with a s) that take a list of paths.
|
@KangOl whoops, good thing you saw the InotifyTrees class, I completely missed it. It'll be nice & clean this way. For point 1, looking at watchdog, they generate all the events manually when a directory is created: https://github.com/gorakhargosh/watchdog/blob/master/src/watchdog/observers/inotify.py#L156 I'm hesitating between submitting a PR to inotify adding this feature somewhere here https://github.com/dsoprea/PyInotify/blame/master/inotify/adapters.py#L287 |
4fc2b60
to
419538d
Compare
From the reactivity of maintainer of |
24940af
to
ecbb498
Compare
Add the alternative of inotify instead of watchdog to watch the addons paths the server was started with. Reason: watchdog spawns 2 threads per path to watch. When there are a lot of addons paths, this can become too costly. With inotify we watch all the repositories in a single thread. https://github.com/dsoprea/PyInotify installation: pip install inotify
Avoid potential tracebacks from the FSWatcher's thread being killed. Drawback: Server shut down can have an extra small delay (only applies when the --dev=reload option is given)
ecbb498
to
0085192
Compare
@KangOl alrighty, 1b) applied & tested on my end Should be good to go. |
Make sure it also works for editor that write in place. |
@antonylesuisse Yeah, it does. It listens to IN_WRITE or IN_MOVED_TO events. (+ IN_CREATE) Both swapping or writing in place are covered by this. |
@KangOl Want any more changes or are we good to go here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@robodoo rebase-ff r+
Merge method set to rebase and fast-forward |
Avoid potential tracebacks from the FSWatcher's thread being killed. Drawback: Server shut down can have an extra small delay (only applies when the --dev=reload option is given) closes #31855 Signed-off-by: Christophe Simonis <chs@odoo.com>
Merged, thanks! |
Avoid potential tracebacks from the FSWatcher's thread being killed. Drawback: Server shut down can have an extra small delay (only applies when the --dev=reload option is given) closes odoo#31855 Signed-off-by: Christophe Simonis <chs@odoo.com>
Add the alternative of inotify instead of watchdog to watch the addons path the server was started with.
Reason: watchdog spawns 2 threads per path to watch. When there are a lot of addons paths, this can become too costly. With inotify we watch all the repositories in a single thread.
https://github.com/dsoprea/PyInotify
installation:
pip install inotify
This PR is a bit more dirty than what's suggested in https://github.com/odoo-dev/odoo/tree/10.0-dev-reload-dve but a lot more efficient.