eclipse-score / eclipse-score/lifecycle

New control API is difficult to use

Open
#611 5 comments 0 reactions 0 assignees View on GitHub
cleanup com enhancement
Dominant language
C++
Stars
6
Forks
34
Avg merge
2d 3h
Merged PRs (30d)
80

Description

### What

Due to the asynchronous design, the new control API introduced in #478 is more difficult to use compared to the old one.

For example, a version of the smoke test:

Before

```cpp
void main()
{
score::mw::lifecycle::ControlClient client{};

TEST_STEP("Control daemon report running")
{
// report running
score::mw::lifecycle::report_running();
}

TEST_STEP("Activate RunTarget Running")
{
score::cpp::stop_token stop_token;
auto result = client.ActivateRunTarget("Running").Get(stop_token);
EXPECT_TRUE(result.has_value()) << "Activating target Running failed: " << result.error().Message();
}

TEST_STEP("Activate RunTarget Startup")
{
score::cpp::stop_token stop_token;
auto result = client.ActivateRunTarget("Startup").Get(stop_token);
EXPECT_TRUE(result.has_value());
}

TEST_STEP("Activate RunTarget Off")
{
client.ActivateRunTarget("Off");
}
}
```

After

```cpp
bool event_received = false;
RunTargetActivationSource event_source;
RunTargetName event_target;
std::mutex event_mutex;
std::condition_variable event_condition;

void push_event(RunTargetActivationSource source, RunTargetName target)
{
{
std::unique_lock event_lock(event_mutex);
event_condition.wait(event_lock, [&] {
return !event_received;
});
event_received = true;
event_source = source;
event_target = target;
}
event_condition.notify_one();
};

void pop_event(std::function callback)
{
{
std::unique_lock event_lock(event_mutex);
event_condition.wait(event_lock, [&] {
return event_received;
});
callback(event_source, event_target);
event_received = false;
}
event_condition.notify_one();
};

void main()
{
std::unique_ptr client;

TEST_STEP("Create client")
{
auto client_result = ILmControl::Create("StateManager/LaunchManager/Instance");
ASSERT_TRUE(client_result.has_value()) << client_result.error().Message();
client = std::move(client_result).value();
}

TEST_STEP("Register callback")
{
const auto result = client->register_run_target_activation_callback(push_event);
ASSERT_TRUE(result.has_value());
}

TEST_STEP("Report running")
{
report_running();
}

pop_event([](RunTargetActivationSource source, RunTargetName target) {
TEST_STEP("Callback for RunTarget Startup")
{
EXPECT_EQ(source, RunTargetActivationSource::kInitialActivation);
EXPECT_EQ(target, "Startup");
}
});

TEST_STEP("Activate RunTarget Running")
{
const auto result = client->activate_run_target("Running", true);
EXPECT_TRUE(result.has_value()) << result.error().Message();
}

pop_event([](RunTargetActivationSource source, RunTargetName target) {
TEST_STEP("Callback for RunTarget Running")
{
EXPECT_EQ(source, RunTargetActivationSource::kStateManagerRequest);
EXPECT_EQ(target, "Running");
}
});

TEST_STEP("Activate RunTarget Startup")
{
const auto result = client->activate_run_target("Startup", true);
EXPECT_TRUE(result.has_value()) << result.error().Message();
}

pop_event([](RunTargetActivationSource source, RunTargetName target) {
TEST_STEP("Callback for RunTarget Startup")
{
EXPECT_EQ(source, RunTargetActivationSource::kStateManagerRequest);
EXPECT_EQ(target, "Startup");
}
});

TEST_STEP("Activate RunTarget Off")
{
const auto result = client->activate_run_target("Off", true);
EXPECT_TRUE(result.has_value()) << result.error().Message();
}
}
```

In the new API, it is not possible to call `activate_run_target` while the `activation_callback` is still running. So, the user has to write multithreaded code.

### Acceptance Criteria (DoD)

- Control API provides methods that do not require external synchronisation

### How

https://github.com/eclipse-score/lifecycle/pull/489#discussion_r3949921034

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the control API introduced in #478, especially activate_run_target and activation_callback, and read the discussion in PR #489. Compare the old and new smoke-test examples to understand the synchronization problem. Done means the API provides methods that do not require external synchronization and the shown control flow can work without user-managed multithreading.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
api
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.