fix(gateway): plugin-provided entities own their bulk data and logs - #560
Merged
Conversation
…logs resolve_app_host_fqns() only looked at effective_fqn(), so an external plugin app resolved to nothing and the rosbag download plus log query for its component matched no source. Share the fault-scope resolver so both paths agree on what an app owns.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes inconsistent “entity -> reporting source” resolution between fault scoping and the HTTP-side bulk-data/log scoping so that plugin-provided (external) entities correctly “own” their rosbags and logs under their bare entity IDs.
Changes:
- Extracted the external-app source resolution rule into
faults::resolve_app_source_fqn()and reused it fromHandlerContextand bulk-data scoping. - Extended bulk-data source filter computation to handle APP entities via the shared resolver, and to include an external component’s own ID alongside its hosted apps.
- Added targeted unit tests covering external apps/components and their expected source filters.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/ros2_medkit_gateway/test/test_handler_context.cpp | Adds tests ensuring external apps resolve to bare entity IDs in resolve_app_host_fqns. |
| src/ros2_medkit_gateway/test/test_bulkdata_handlers.cpp | Adds tests validating bulk-data source filters for external apps/components. |
| src/ros2_medkit_gateway/src/http/handlers/handler_context.cpp | Updates app-host source resolution to use faults::resolve_app_source_fqn(). |
| src/ros2_medkit_gateway/src/http/handlers/bulkdata_handlers.cpp | Updates bulk-data source filter computation for APP and external COMPONENT cases. |
| src/ros2_medkit_gateway/src/core/faults/fault_scope.cpp | Introduces resolve_app_source_fqn() and reuses it in fault scoping. |
| src/ros2_medkit_gateway/include/ros2_medkit_gateway/http/handlers/handler_context.hpp | Updates documentation to describe source resolution semantics (external apps -> bare ID). |
| src/ros2_medkit_gateway/include/ros2_medkit_gateway/core/faults/fault_scope.hpp | Declares resolve_app_source_fqn() (note: header doc needs a small terminology update per review comment). |
Comments suppressed due to low confidence (1)
src/ros2_medkit_gateway/include/ros2_medkit_gateway/core/faults/fault_scope.hpp:40
- The doc comment for
resolve_entity_source_fqnsstill says it resolves “App effective-FQNs”, but APP resolution now goes throughresolve_app_source_fqn()(external apps resolve to their bare entity id, and unbound non-external apps resolve to nothing). The header comment should match the actual semantics so callers don’t accidentally rely on “effective FQN only” behavior.
/// Resolve the set of App effective-FQNs that fall within an entity's scope by
/// walking the entity cache:
/// - APP: the app's own effective FQN
/// - COMPONENT: every hosted app's FQN
/// - AREA: every app under the area and its (recursive) subareas
An external app has no ROS binding, so the fqn path produced no source filter and the rosbag its own fault detail advertises answered "Bulk-data not found for this entity" with the file on disk. External components have the same hole for faults they report under their own id.
mfaferek93
force-pushed
the
fix/plugin-entity-bulk-data-v2
branch
from
July 26, 2026 20:27
e2e55da to
d571e98
Compare
bburda
reviewed
Jul 27, 2026
Collaborator
There was a problem hiding this comment.
Additional findings outside the diff:
- Could you also look at the APP branch in
log_handlers.cpp(the lastelse)? It queries{entity.fqn}, which is""for an external app, soGET /apps/<external_app>/logsreturns nothing even though the entries are stored under the entity id. The logs claim in the description holds for functions, areas and components only. - Could you add the external component's own id in the COMPONENT branch there as well? Right now such a component owns its rosbags but not its logs.
- Please check the cyclic subscription samplers in
gateway_node.cpp. They still resolve with a raweffective_fqn()and use a privatefilter_faults_by_fqns, so a subscription on an external app returns"Entity no longer available"every cycle, and an external component gets an empty fault list. - Could you update the docs in this PR?
docs/api/rest.rstsays component logs query child apps "by exact FQN", andbulkdata_handlers.hppstill documents the old APP and COMPONENT behaviour of the function you changed. - Would you mind adding an integration test for the reported 404?
test_external_app_fault_rollup.test.pyandexternal_app_fault_manifest.yamlalready set up an external app, so reporting a fault there and downloading the advertisedbulk_data_uriwould cover it.
bburda
reviewed
Jul 27, 2026
…rule Every entity type now computes its rosbag source filters via resolve_entity_source_fqns, so AREA recurses subareas and FUNCTION follows component hosts instead of 404ing bags their fault lists advertise. The download ownership check reads the fault once and tests it with the boundary-aware matcher, closing the prefix hole between sibling ids.
New logs::query_entity_logs resolves exact sources via the fault-scope rule (external app bare id, external component own id) and merges the namespace prefix query for COMPONENT/AREA, so hosting an external app no longer drops namespace node logs. The faults and logs samplers route through the shared resolvers; the private fault filter copy in gateway_node is gone.
Publish a capture topic so a real bag is flushed when the external app's fault confirms, then assert the app download and the area-advertised bulk_data_uri return 200 with bytes, plus area and function listings. Fails against the namespace-path area scope with an empty area listing.
The namespace query now merges with resolved sources instead of acting as a fallback; say so where the endpoint list summarises it.
Collaborator
Author
|
The outside-diff findings, all on the branch now:
Agreed on the last note: the namespace filter never matched an app source in the listing, so the visible change is only the stricter download check. |
bburda
approved these changes
Jul 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #558.
Fault scoping and bulk-data scoping disagreed about what source an entity owns,
so a plugin-provided entity could not download the rosbag its own fault detail
advertised.
effective_fqn())moves out of the anonymous namespace into
faults::resolve_app_source_fqn, andboth
collect_app_fqnandHandlerContext::resolve_app_host_fqnsuse it, sothere is one definition of the rule rather than two that drift.
compute_bulkdata_source_filtersgains the two branches it was missing: an APPentity resolves through the same helper instead of falling through to an empty
fqn, and an external COMPONENT owns its own id alongside its hosted apps -the same rule
collect_component_app_fqnsalready applies for faults.Logs go through the same resolver, so
LogManager::get_logsis fixed with it.Tests:
ExternalAppResolvesToItsBareEntityId,ExternalAppWithStrayBindingStillResolvesToItsId,ComponentWithExternalAppsReturnsBareEntityIds,ExternalComponentAlsoOwnsItsOwnId.Each fails on the pre-fix resolver. Full gateway suite: 4289 tests, 0 failures,
484 skipped; clang-format clean.
One behaviour change worth naming: a component that hosts external apps no longer
falls through to the
fqn/namespace_pathprefix filter, because thatfall-through only fires on an empty source set. That affects a manifest component
whose bags are sourced from a ROS namespace and which also hosts external apps.