Skip to content

Implement new control API - #489

Open
danth wants to merge 12 commits into
eclipse-score:mainfrom
etas-contrib:control-api
Open

danth wants to merge 12 commits into
eclipse-score:mainfrom
etas-contrib:control-api

Conversation

@danth

@danth danth commented Aug 18, 2026

Copy link
Copy Markdown
Member

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_Manager application type is now aliased to Reporting_and_Supervised.

    Instead, mw::com access control must be used to prevent unwanted processes acting as state managers.

  • There is a workaround to make the process_fd_leak test pass, because there is no possibility to set O_CLOEXEC on mw::com's file descriptors when they are created.

    I've opened an issue to fix this upstream: Set CLOEXEC on file descriptors communication#1064

  • External documentation needs to be updated before this is released.

Relevant issues

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

License Check Results

🚀 The license check job ran with the Bazel command:

bazel run --lockfile_mode=error //:license-check

Status: ⚠️ Needs Review

Click to expand output
[License Check Output]
Extracting Bazel installation...
Starting local Bazel server (8.7.0) and connecting to it...
INFO: Invocation ID: 888f0780-f607-43de-9fe8-7fb3cd200f21
Computing main repo mapping: 
Computing main repo mapping: 
Computing main repo mapping: 
Loading: 
Loading: 0 packages loaded
Loading: 0 packages loaded
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Loading: 0 packages loaded
    currently loading: 
Analyzing: target //:license-check (1 packages loaded, 0 targets configured)
Analyzing: target //:license-check (1 packages loaded, 0 targets configured)

Analyzing: target //:license-check (51 packages loaded, 10 targets configured)

Analyzing: target //:license-check (88 packages loaded, 10 targets configured)

Analyzing: target //:license-check (144 packages loaded, 737 targets configured)

Analyzing: target //:license-check (156 packages loaded, 4383 targets configured)

Analyzing: target //:license-check (158 packages loaded, 8562 targets configured)

Analyzing: target //:license-check (163 packages loaded, 9368 targets configured)

Analyzing: target //:license-check (169 packages loaded, 9541 targets configured)

Analyzing: target //:license-check (172 packages loaded, 11426 targets configured)

INFO: Analyzed target //:license-check (173 packages loaded, 11555 targets configured).
[12 / 16] Creating runfiles tree bazel-out/k8-opt-exec-ST-d57f47055a04/bin/external/score_tooling+/dash/tool/formatters/dash_format_converter.runfiles [for tool]; 0s local ... (2 actions, 1 running)
INFO: Found 1 target...
Target //:license.check.license_check up-to-date:
  bazel-bin/license.check.license_check
  bazel-bin/license.check.license_check.jar
INFO: Elapsed time: 25.810s, Critical Path: 0.69s
INFO: 16 processes: 4 disk cache hit, 12 internal.
INFO: Build completed successfully, 16 total actions
INFO: Running command line: bazel-bin/license.check.license_check ./formatted.txt <args omitted>
usage: org.eclipse.dash.licenses.cli.Main [-batch <int>] [-cd <url>]
       [-confidence <int>] [-ef <url>] [-excludeSources <sources>] [-help] [-lic
       <url>] [-project <shortname>] [-repo <url>] [-review] [-summary <file>]
       [-timeout <seconds>] [-token <token>]

@danth
danth requested a deployment to workflow-approval August 18, 2026 13:40 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 18, 2026 13:40 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 18, 2026 13:42 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 18, 2026 13:42 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 08:17 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 08:17 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 10:01 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 10:01 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 13:33 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 19, 2026 13:33 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 21, 2026 15:00 — with GitHub Actions Waiting
@danth
danth requested a deployment to workflow-approval August 21, 2026 15:00 — with GitHub Actions Waiting

@WilliamRoebuck WilliamRoebuck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread score/launch_manager/src/daemon/src/process_group_manager/control_provider.cpp Outdated
Comment thread score/launch_manager/src/daemon/src/process_group_manager/control_provider.cpp Outdated
Comment thread tests/integration/complex_monitoring/control_client_test_driver.cpp
Comment thread tests/utils/test_helper/test_helper.hpp
Comment thread examples/control_application/control_daemon.cpp
Comment thread score/launch_manager/src/daemon/src/control/details/control_provider.cpp Outdated
Comment thread examples/control_application/control_daemon.cpp Outdated
Comment thread score/launch_manager/src/daemon/src/control/icontrollable_graph.hpp Outdated
Comment thread score/launch_manager/src/daemon/src/control/icontrollable_graph.hpp Outdated
Comment thread score/launch_manager/src/daemon/src/control/BUILD Outdated
Comment thread score/launch_manager/src/daemon/src/control/control_provider.cpp Outdated
Comment thread score/launch_manager/src/daemon/src/control/control_provider.cpp Outdated
Comment thread score/launch_manager/src/daemon/src/control/control_provider.hpp

~ControlProvider() = default;

// Cannot be moved because callbacks capture the ControlProvider by reference.

@danth danth Sep 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if the comment in the code is quite correct. Previously, launch manager would segfault after the ControlProvider was moved. I am only assuming that this is the explanation.

Because of this restriction, ControlProvider::Create has to allocate and return a reference. It would be good to avoid it if anyone knows how...

@danth

danth commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

Explanation of how get_active_run_target is handled:

PlantUML diagram

Comment thread score/launch_manager/src/execution_error.h
case fb::ApplicationType::State_Manager:
return ApplicationType::StateManager;
// These are now equivalent as access control is done via mw::com
return ApplicationType::ReportingAndSupervised;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would still make sense to keep all of this to somehow limit who can change run targets?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be done through mw::com access control.

See also this and this.

namespace score::mw::lifecycle::internal
{

class IControllableGraph

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this name, Maybe something like IComponentController? Probably should also be in process_group_manager

namespace score::mw::lifecycle::internal
{

class ControlProvider

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to also add a brief for what the class does

}
LmControlSkeleton skeleton = std::move(skeleton_result).value();

auto* control_provider = new ControlProvider{std::move(skeleton), graph};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why allocate this? could just create and move into Result

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


const std::optional<IdentifierHash> new_state = IdentifierHash::if_exists(request.run_target_name.data());
if (!new_state.has_value())
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think logging errors would also be a good idea here.

}

const std::lock_guard<std::mutex> lock(IdentifierHash::get_registry_mutex());
const std::string& name = IdentifierHash::get_registry()[result.value().data()];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you make a Result<std::string_view> IdentifierHash::get_name(IdentifierHash) method as this can throw? originally I think the registry was made just for logging but since its becoming needed for the internal logic I think making it safer would be a good idea.

ControlProvider& operator=(const ControlProvider&) = delete;
ControlProvider operator=(ControlProvider&&) = delete;

private:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you go through and check which methods can be marked as noexcept? I think probably all methods here should be?

IdentifierHash process_identifier;
};

struct [[nodiscard]] GetActiveRunTarget

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need briefs

const IdentifierHash state = getProcessGroupState();

RunTargetActivationSource source;
if (is_initial_state_transition_)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think this is clang-tidy warning to not have braces around the if

{
// 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 should have been activated";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some test drivers verify activation via a marker file on disk (e.g. EXPECT_TRUE(std::filesystem::exists(fallback_file))). Now that get_active_run_target() exists, could tests assert against client->get_active_run_target() instead — checking the daemon's own state rather than a side effect? Not a blocker, could be a fast-follow.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this can be cleaned up as a follow-up.

See also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

Initial implementation of mw::com-based control API (daemon) Create a design for using mw::com for Control API

6 participants