-
Notifications
You must be signed in to change notification settings - Fork 192
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
API: Add method to start the daemon to DaemonClient
#5625
Conversation
Great, thanks a lot @sphuber ! Even just the refactoring alone makes the code easier to understand. Before I go through it line by line, just one question:
Controlling the daemon of the "current" profile via the Python API is already a great step forward, but it seems to me that a fully-fledged daemon Python API should be able to control a daemon for a specific profile specified by the caller - see e.g. Would it be possible to make the profile an optional parameter in the daemon API that is pre-filled with the loaded profile when a profile is already loaded (e.g. when used via the |
Well, in a sense, it already is. The from aiida.engine.daemon.client import get_daemon_client
client = get_daemon_client()
client.start_daemon()
# or
from aiida.engine.daemon.client import DaemonClient
from aiida.manage import load_profile
profile_name = 'profile-a'
profile = load_profile(profile_name)
client = DaemonClient(profile)
client.start_daemon() Does that work you think? By the way: I am also working on the process control API, but that required the daemon refactoring anyway for the tests, so I thought to add that in a separate PR. |
Sorry, I should have looked more closely. That makes sense!
Great! Then let me have a quick look through the code |
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.
Thanks @sphuber !
Just some minor comments.
Finally, if you want to go through with the renaming of "runner" to "worker", you may want to do a full-text search on the repository - e.g. the term appears in the docs, in the verdi config, etc.
I also prefer the term "worker" but I'm also fine with keeping "runner".
arbiter = None | ||
if pidfile is not None: | ||
pidfile.unlink() | ||
@verdi_daemon.command('worker') |
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.
I understand that you feel this makes more sense as a location - at the same time, have you ever encountered a use case for this that was not related to AiiDA development?
If so, perhaps this use case should be documented in the aiida docs. If not, I guess we could also leave this command in verdi devel
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.
It's not so much for developing, but can be useful for debugging if you want to run a single daemon worker in the foreground. I would keep it under verdi daemon
as it centralizes all daemon code, especially since circus also calls verdi daemon worker
to spawn a new worker. It is a bit weird to have the actual daemon call verdi devel run_daemon
as a daemon worker.
aiida/engine/daemon/client.py
Outdated
""" | ||
The protocol to use to for the controller of the Circus daemon | ||
""" | ||
"""The protocol to use to for the controller of the Circus daemon.""" |
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.
"""The protocol to use to for the controller of the Circus daemon.""" | |
"""The protocol to use for the controller of the Circus daemon.""" |
aiida/engine/daemon/client.py
Outdated
The endpoint is defined by the controller endpoint, which used the port that was written to the port file upon | ||
starting of the daemon. | ||
|
||
.. note:: This is quite slow the first time it is run due to the import of ``zmq.ssh`` in ``circus/utils.py`` in |
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.
Do we make use of zmq.ssh
or is this import effectively superfluous for us?
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.
The import is indirect, through us importing circus.client.CircusClient
. Note that I did not add this comment, it has been there for a while (added in b39a9be). That commit simply moved the import from top-level to within the function, probably to not have it slow down the tab-completion of verdi
. I just tested importing from zmq import ssh
in a shell and it doesn't seem that slow. I think we can remove the comment and even consider moving the import to top level. We have the verdi
load time test to warn if we exceed the load time
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.
Thanks. Yes, no need to fix it in this PR.
If you believe it may be a valid candidate to things up (e.g. because we don't use the ssh
thing), perhaps worth mentioning it here, that's all.
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.
I moved the import top-level and it actually caused the verdi load time test to fail. Now this could have been coincidence, but best to keep the import in the method. No real reason not to.
Note that we should not rename everything from The outside facing language for AiiDA users should reference daemon workers but that doesn't mean that the |
ec508bd
to
1d616ac
Compare
So far, the daemon could only be started through `verdi` and there was no way to do it from the Python API. Here we add the `start_daemon` method to the `aiida.engine.daemon.client.DaemonClient` class which will start the daemon when called. To start the daemon, the function will actually still invoke the `verdi` command through a subprocess. The reason is that starting the daemon will put the calling process in the background, which is not the desired behavior when calling it from the API. The actual code that launches the circus daemon is moved from the `verdi` command to the `_start_daemon` method of the `DaemonClient`. In this way, the daemon functionality is more self-contained. By making it a protected method, we signal that users of the Python API should probably not use it, but use the public `start_daemon` instead. This implementation may seem to have some circularity, as `start_daemon` will call a `verdi` command, which in turn will call the `_start_daemon` method of the `DaemonClient`. The reason for this is that the `verdi` command ensures that the correct profile is loaded before starting the daemon. We could make a separate CLI end point independent of `verdi` that just serves to load a profile and start the daemon, but that seems unnecessarily complicated at this point. Besides the added function, which was the main goal, the code is also refactored considerably. The implementation of the command line command `verdi daemon start-circus` is now moved to the `_start_circus` method of the `DaemonClient` class. The `verdi devel run_daemon` command is moved to `verdi daemon worker`, which makes more sense as a location. This command launches a single daemon worker, which is nothing more than an AiiDA process that runs a `Runner` instance in blocking mode. The `verdi daemon start` will run a circus daemon that manages instances of these daemon workers. To better match the nomenclature, the module `aiida.engine.daemon.runner` was renamed to `worker`.
1d616ac
to
a63f8ef
Compare
Ok. I'm also in favor of not changing user-facing API if we don't need to. Since the difference between a "runner" and a "worker" is not going to be intuitively obvious to most users, you may want to consider mentioning the difference at least somewhere in the docs. Here are places in the docs that mention "runner" (maybe all fine; just wanted to make sure you agree):
|
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.
in any case, from my side the changes are good, no need to re-review from my side.
You are right, some of these should actually be changed to daemon worker. Wondering if I should still do this in this PR, or just revert the name change in this PR for now and leave that for another time. |
Up to you, feel free to go ahead - no need to slow down for this |
So far, the daemon could only be started through
verdi
and there wasno way to do it from the Python API. Here we add the
start_daemon
method to the
aiida.engine.daemon.client.DaemonClient
class which willstart the daemon when called.
To start the daemon, the function will actually still invoke the
verdi
command through a subprocess. The reason is that starting the daemon
will put the calling process in the background, which is not the desired
behavior when calling it from the API. The actual code that launches the
circus daemon is moved from the
verdi
command to the_start_daemon
method of the
DaemonClient
. In this way, the daemon functionality ismore self-contained. By making it a protected method, we signal that
users of the Python API should probably not use it, but use the public
start_daemon
instead.This implementation may seem to have some circularity, as
start_daemon
will call a
verdi
command, which in turn will call the_start_daemon
method of the
DaemonClient
. The reason for this is that theverdi
command ensures that the correct profile is loaded before starting the
daemon. We could make a separate CLI end point independent of
verdi
that just serves to load a profile and start the daemon, but that seems
unnecessarily complicated at this point.
Besides the added function, which was the main goal, the code is also
refactored considerably. The implementation of the command line command
verdi daemon start-circus
is now moved to the_start_circus
methodof the
DaemonClient
class. Theverdi devel run_daemon
command ismoved to
verdi daemon worker
, which makes more sense as a location.This command launches a single daemon worker, which is nothing more than
an AiiDA process that runs a
Runner
instance in blocking mode. Theverdi daemon start
will run a circus daemon that manages instances ofthese daemon workers. To better match the nomenclature, the module
aiida.engine.daemon.runner
was renamed toworker
.