-
Notifications
You must be signed in to change notification settings - Fork 0
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
Add abort api #194
Add abort api #194
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report? Let us know! |
evolver/app/main.py
Outdated
app.state.evolver.abort() | ||
# Disable commit also in persistent config in case application needs to restart | ||
app.state.evolver.config_model.enable_commit = False | ||
app.state.evolver.config_model.save(app_settings.CONFIG_FILE) |
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 think we'll need to repon that convo about stashing state vs configuration, as in #185.
There seems to be some flip-flopping on what app_settings.CONFIG_FILE
is for. I was initially led to believe that it was for state, however, during #185 it was argued that it very much isn't for state, but for updating the configuration, but only as intended bu the user. The latter point emphasized by the fact that only the update
endpoint should clobber app_settings.CONFIG_FILE
as this is the only place where configuration is intentionally changed by the user.
We should not conflate state and configuration as I did before. Updating the configuration file here from the evolver's dynamic state (which can very much differ from its configuration) is exactly the same as having done so in #185.
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 is config, and the abort should update like here - but I see the point about potential internal changes between update and abort. I will change it to update directly from the file
evolver/hardware/demo.py
Outdated
def commit(self): | ||
self.comitted = copy(self.proposal) | ||
|
||
def abort(self): | ||
self.aborted = True |
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.
What's this attr for?
Doesn't this need to go in the interface
class to be adequately utilized?
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.
this is the demo, the attr is specifically for testing
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 think this would be misleading to someone interpreting the "demo" as something to mimic in their implementations, which they shouldn't.
This would be better off in the test code itself, e.g., via a monkeypatch or something similar.
cmd = [b"0"] * self.slots | ||
with self.serial as comm: | ||
comm.communicate(SerialData(addr=self.addr, data=cmd)) |
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.
This looks like more than just abort code, as mentioned before, couldn't this go in another abstractmethod named, e.g., "reset", "idle", "off", or "init", etc, that then abort
just calls? abort
wouldn't have to be abstract.
Looks to me like these should be called upon initialization as a way for controlling a baseline on the hardware's physical state.
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 believe the above is what it takes to abort the operation of the device. Do you mean like naming it off
since that would look less alarming if called upon initialization (if we do so in the future)?
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.
Not entirely, but kinda yeah, I meant that we both mentioned in #197 it might be desirable to exec these commands upon initial startup, in which case it's not really an "abort" but more of a ground/rest/init/off state.
Technically it's not aborting anything as we have to actually send a commit to command the hardware to some state. Evolver.abort
is an "abort" but HardwareDriver.abort
isn't.
Either way, I didn't mean anything complicated just something like the following:
class HardwareDriver(...):
@abstractmethod
def init(self, *args, **kwargs): # could be called "reset"
""" Implement to command hardware to its ground/off state. This could be called upon startup/abort."""
...
def abort(self):
self.init()
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.
Actually the device abort does send the command directly, no commit required. I'm not sure yet what we will do at startup, but I can definitely rename the device method to off
instead. "abort" speaks to the immediacy of it though...
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've renamed driver method to off
and added docstring for method expectations. I will defer doing anything with startup in this PR.
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.
Actually the device abort does send the command directly, no commit required.
I only meant that it still has to send a command period and not just block subsequent commands. That these hardware methods don't alter the config, they themselves don't "block" future commanding at all etc, and that they are in fact completely oblivious to this concept (at least they should be). They only alter the hardware to some specific state, a state in this instance that is encoded in the semantics of this function name - which isn't "abort".
"abort" speaks to the immediacy of it though...
Agreed, and evolver.device.Evolver.abort
is cool to be named such as it does actually "abort" subsequent control etc, though there's still scope for argument around the fact that it still pings the hardware and reads data so doesn't completely "abort", see #199 #196.
"abort" speaks to the immediacy of it though...
At the same time, however, this isn't entirely true due to the significant (1-2s) latency per call and the fact that these are turned off in sequence rather than proposals being set
and committed all at once.
config = Evolver.Config.load(app_settings.CONFIG_FILE) | ||
config.enable_control = False | ||
config.enable_commit = False | ||
config.save(app_settings.CONFIG_FILE) |
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.
Does this mean that whilst the user can hit this endpoint to stop the control, they have to use the update
endpoint to start/restart it and have to specifically do so by (hopefully) only manually changing these two flags to True
every 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.
yes!
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 don't think this is a sufficient user interface and have opened #198 to add a "start" endpoint.
evolver/tests/test_device.py
Outdated
def patched_abort(self): | ||
self.aborted = True |
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 think it would be better to still call the original abort
here, to future-proof the test if something actually gets added to NoOpEffectorDriver.abort
, rather than circumvent the test, no?
51eb7ca
to
1ee5082
Compare
3ff558a
to
fdebb69
Compare
app.state.evolver.abort() | ||
# Disable commit also in persistent config in case application needs to restart | ||
config = Evolver.Config.load(app_settings.CONFIG_FILE) | ||
config.enable_control = False |
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.
FYI I've opened #199 for us to also consider aborting the read.
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.
👍
Sets up API for abort, which would put all devices into a stopped state (whatever that means for a particular device still in the powered-on state). The device-level action both stops the control components of loop and also the all devices, while the web-app (application-level) aborts the device and writes out the control disablement to config, such that a restart would not inadvertently continue normal operation without user intervention (given the current mainline behavior of the system)
Resolves #121