Implement new control API - #489
Conversation
License Check Results🚀 The license check job ran with the Bazel command: bazel run --lockfile_mode=error //:license-checkStatus: Click to expand output |
WilliamRoebuck
left a comment
There was a problem hiding this comment.
A really great implementation, I have some small cleanup suggestions. I also rambled a bit about the API but I understand I may be a bit late on this so apologies if it's not relevant. As I'll be away from tomorrow, just comment and resolve if you disagree or I've misunderstood
| // workaround to detect we're in fallback | ||
| // This verifies that a fallback process was actually started - the launch manager | ||
| // did not just send an event without taking the action. | ||
| EXPECT_TRUE(std::filesystem::exists(fallback_file)) << "Fallback run target was not activated"; |
There was a problem hiding this comment.
Can we just use get_active_run_target() here? Rather than repeating this step each test, we could have a single test to verify that a component configured to launch in fallback actually launched
There was a problem hiding this comment.
I tried to make minimal changes from the old tests, but this can be cleaned up.
I think we should have a separate test which makes sure that the callbacks are telling the truth, then no further verification is needed in the other tests.
There was a problem hiding this comment.
I think these improvements could be done in a separate pull request, so long as the tests are passing in their current state. :))
| case fb::ApplicationType::Reporting_And_Supervised: | ||
| return ApplicationType::ReportingAndSupervised; | ||
| case fb::ApplicationType::State_Manager: | ||
| return ApplicationType::StateManager; |
There was a problem hiding this comment.
I would recommend to translate fb::ApplicationType::State_Manager into ApplicationType::ReportingAndSupervised until we remove State_Manager from configuration schema.
Additionally we probably need to create work item to change configuration schema and to adapt translation script scripts/config_mapping/lifecycle_config.py
There was a problem hiding this comment.
I have reverted the removal for now, and we just translate it to Reporting_and_Supervised. See also.
| const ActivateRunTargetRequest& request) | ||
| { | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( | ||
| request.mode == ActivationMode::kForced, "Only ActivationMode::kForced is implemented"); |
There was a problem hiding this comment.
If we don't have a work item already, we should create one.
The queue is the intended mode and forced flag should be used sparingly...
| { | ||
| const auto instance_specifier_result = | ||
| InstanceSpecifier::Create(std::string{"LaunchManager/StateManager/Instance"}); | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE( |
There was a problem hiding this comment.
Could we give this error back to the user, e.g. with an init() method or a Create(..) call?
Then we can log an error in main and cleanly shutdown the process.
I suspect people run into this problem frequently when they first try to start LM without a mw::com config file that has this exact instance specifier defined. Then it would be more user friendly to have a nice error message instead of crashing on an assertion.
| instance_specifier_result.has_value(), instance_specifier_result.error().Message().data()); | ||
|
|
||
| auto skeleton_result = LmControlSkeleton::Create(instance_specifier_result.value()); | ||
| SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD_MESSAGE(skeleton_result.has_value(), skeleton_result.error().Message().data()); |
There was a problem hiding this comment.
Same here, I would also pass this back to main and log a nice error with more context.
E.g. Failed to setup mw::com communication for LmControl service...Error: <mw::com error>
| namespace score::mw::lifecycle::internal | ||
| { | ||
|
|
||
| class ControlProvider |
There was a problem hiding this comment.
Maybe we can do it as a subsequent step in another PR to not block this one, but we should think how we can restructure the class so we can unit test it. I am not sure if we can provoke all the error cases without having some mocking mechanism in place.
There was a problem hiding this comment.
I have been working on some unit tests locally... I think if we could somehow call the handle_ methods directly in the test, then it would be fairly simple to check their behaviour independently from mw::com. I'm not sure the best way to structure that though, as just marking them public would not be ideal.
| Result<IdentifierHash> ProcessGroupManager::get_active_run_target() const | ||
| { | ||
| return &process_interface_; | ||
| auto promise = concurrency::InterruptiblePromise<Result<IdentifierHash>>{}; |
There was a problem hiding this comment.
If I remember correctly the Future/Promise from Score baselibs requires heap allocation. In that case we cannot really use this at runtime.
However, for this initial implementation I think it is still fine and we can exchange this later to not add too much complexity within this PR. Its a nice clean implementation using future promise.
This works around the `Graph` class not being thread safe.
This resolves several edge cases which the new version did not handle properly.
This pull request adapts the launch manager (and tests) to use the new control API based on
mw::com, and removes the old API.Notable points
The
State_Managerapplication type is now aliased toReporting_and_Supervised.Instead,
mw::comaccess control must be used to prevent unwanted processes acting as state managers.There is a workaround to make the
process_fd_leaktest pass, because there is no possibility to setO_CLOEXEConmw::com's file descriptors when they are created.I've opened an issue to fix this upstream: Set
CLOEXECon file descriptors communication#1064External documentation needs to be updated before this is released.
Relevant issues