eclipse-score / eclipse-score/communication
Improvement: `applicationID` configuration — is a separate mechanism (outside `mw_com_config.json`) planned?
- Dominant language
- C++
- Stars
- 62
- Forks
- 97
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 72
Description
## Context
`applicationID` is the stable, restart-invariant TransactionLogId used by LoLa. In `score_communication` it is:
- Parsed from the `global` section of `mw_com_config.json` — key `applicationID`, handled in `config_parser.cpp` (`kApplicationIdKey`, `ParseGlobalConfiguration`), stored in `GlobalConfiguration::SetApplicationId`.
- Documented to **default to the process UID** when unset: `i_shm_path_builder.h` ("which defaults to user ID but can be set in configuration") and `proxy.cpp` ("either the configured 'applicationID' or the process UID as a fallback").
- Used to build the SHM names / transaction-log identity, so it must **uniquely identify a process** among all LoLa processes sharing the same shared-memory namespace.
## The problem we hit (multi-process, single-config deployment)
S-CORE's config model is **one `mw_com_config.json` per deployment/application**. `applicationID` lives inside that file's `global` section, i.e. it is a **deployment-level** value. But semantically it is a **process-level** identity:
- In a split-process deployment (our HFC: `haptic_force_controller`, `zone_adapter`, `telemetry` all run from the same deployment), every process reads the same `global.applicationID` → all processes get the same TransactionLogId.
- The UID fallback does not help when processes run as the same user — all HFC processes run as `uid 0`, so unset → all share `TransactionLogId 0` (ambiguous/overlapping transaction-log recovery and SHM path collisions).
- Our only workaround was to **fork the entire config per process** just to change one number: we keep one canonical `mw_com_config.json` in git (appID 7001) and generate `mw_com_config_zone_adapter.json` (7002) / `mw_com_config_telemetry.json` (7003) with a small generator script. That duplicates a ~380-line config three times and risks drift.
## Suggested approach (for discussion)
One candidate mechanism would be an **environment-variable override `SCORE_APPLICATION_ID`** with the resolution order:
```
SCORE_APPLICATION_ID env var > config "applicationID" > getuid() fallback
```
Rationale for precedence: in a shared-config deployment the config carries the deployment-wide default, while each process's launch script sets the env var as the **per-process specialization** — so the env var must win. The `getuid()` fallback stays as the last resort.
The change is small and localized. The resolution currently happens in one place, `Runtime::DetermineApplicationIdentifier()` in `score/mw/com/impl/bindings/lola/runtime.cpp`:
```cpp
std::uint32_t Runtime::DetermineApplicationIdentifier(const Configuration& config) const noexcept
{
const auto& global_config = config.GetGlobalConfiguration();
const auto application_id = global_config.GetApplicationId();
if (application_id.has_value())
{
return application_id.value();
}
else
{
score::mw::log::LogInfo("lola") << "No explicit applicationID configured. Falling back to using process UID. "
<< "Ensure unique UIDs for applications using mw::com.";
static_assert(sizeof(uid_t) <= 4, "For more than 32 bits we cannot guarantee the key to be unique");
return static_cast(os::Unistd::instance().getuid());
}
}
```
Sketch of the change (plus a small `os`/env helper, following the existing `os::Unistd` abstraction pattern):
```cpp
std::uint32_t Runtime::DetermineApplicationIdentifier(const Configuration& config) const noexcept
{
// 1) per-process override: SCORE_APPLICATION_ID (highest priority)
if (const auto env_id = os::Environment::instance().GetUint32("SCORE_APPLICATION_ID"); env_id.has_value())
{
return env_id.value();
}
// 2) deployment config: global.applicationID
const auto& global_config = config.GetGlobalConfiguration();
if (const auto application_id = global_config.GetApplicationId(); application_id.has_value())
{
return application_id.value();
}
// 3) legacy fallback: process UID
score::mw::log::LogInfo("lola") << "No explicit applicationID configured. Falling back to using process UID. "
<< "Ensure unique UIDs for applications using mw::com.";
static_assert(sizeof(uid_t) <= 4, "For more than 32 bits we cannot guarantee the key to be unique");
return static_cast(os::Unistd::instance().getuid());
}
```
This sketch is only to illustrate the idea — we are not in a position to contribute upstream. If maintainers are interested in this direction, the questions below (variable name, precedence, abstraction) would need confirmation before anyone implements it.
## Question for maintainers
1. **Is there already a plan to make `applicationID` configurable outside `mw_com_config.json`?** (env var / CLI / per-process section / separate identity file). We did not find any existing mechanism — config or `getuid()` only.
2. If not, does the proposal above (env var, priority over config and UID) fit S-CORE's conventions? Feedback wanted on: name, precedence, and whether `os::Environment` (or equivalent) is the right abstraction to use.
3. Separately: is the silent `getuid()` fallback intended to remain, or should a missing `applicationID` be **validated/required** in multi-process deployments (where every process sharing the SHM namespace must have a unique identity)?
## Supporting info
- Without distinct applicationIDs, our split-process deployment produced ambiguous transaction-log recovery in shared memory (all processes had the same TransactionLogId), which surfaced as LoLa subscription/recovery failures.
- With distinct applicationIDs (7001/7002/7003) the full deployment runs cleanly (15/15 tests). Today we work around the limitation by generating per-process config files (`scripts/gen_mw_com_configs.py`), which duplicates the whole config and risks drift; an env-var mechanism would remove that.
- Note: we are reporting this for the maintainers' awareness; we are not in a position to contribute a fix upstream ourselves.
Contributor guide
Research direction
Start with Runtime::DetermineApplicationIdentifier() in score/mw/com/impl/bindings/lola/runtime.cpp, then review config_parser.cpp and the existing os::Unistd abstraction. Confirm the supported per-process mechanism, precedence, variable name, and fallback policy with maintainers before implementation. Done means distinct identities work with one shared configuration while the existing configuration and UID behavior remain defined.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- distributed-systems, operating-systems
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100