Skip to content

feat: Entity registration HTTP API#3230

Merged
albinsuresh merged 9 commits intothin-edge:mainfrom
albinsuresh:feat/entity-management-http-apis
Jan 17, 2025
Merged

feat: Entity registration HTTP API#3230
albinsuresh merged 9 commits intothin-edge:mainfrom
albinsuresh:feat/entity-management-http-apis

Conversation

@albinsuresh
Copy link
Copy Markdown
Contributor

@albinsuresh albinsuresh commented Nov 6, 2024

Proposed changes

  • Refactor file-transfer logic into its own module
  • Add entity store endpoints to existing tedge HTTP server
  • Integrate the HTTP endpoints with the entity store
  • Refactor file transfer API logic to its own module
  • Publish entities registered via HTTP APIs to the MQTT broker
  • Accept registration messages via MQTT as well
  • Remove entity_store usage from the mappers, extracting only the external ID aspects from it
  • Handle auto-registration
  • Rename existing file_transfer_server module into tedge_server

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Improvement (general improvements like code refactoring that doesn't explicitly fix a bug or add any new functionality)
  • Documentation Update (if none of the other choices apply)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Paste Link to the issue


Checklist

  • I have read the CONTRIBUTING doc
  • I have signed the CLA (in all commits with git commit -s)
  • I ran cargo fmt as mentioned in CODING_GUIDELINES
  • I used cargo clippy as mentioned in CODING_GUIDELINES
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Further comments

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Nov 13, 2024

Robot Results

✅ Passed ❌ Failed ⏭️ Skipped Total Pass % ⏱️ Duration
556 0 2 556 100 1h32m59.355476s

@@ -1,4 +1,6 @@
//TODO Rename this module to tedge_server
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 would prefer http_server, stressing this is about HTTP while tedge is obvious in the context of tedge-agent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will be renamed as suggested, right before merging this PR.

//TODO Rename this module to tedge_server
pub mod actor;
pub mod error;
mod file_transfer_controller;
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 not simply file_transfer?

Copy link
Copy Markdown
Contributor Author

@albinsuresh albinsuresh Nov 14, 2024

Choose a reason for hiding this comment

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

I've renamed it as you suggested.

It actually started with entity_store_controller, as I didn't want to name it entity_store to differentiate this from the original entity store and hence ended up adding the controller suffix. Did the the same for file_transfer as well.

But, now I'm wondering if naming them file_transfer_service and entity_store_service would have been clearer/better.

Copy link
Copy Markdown
Contributor

@didier-wenzek didier-wenzek left a comment

Choose a reason for hiding this comment

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

I suggest to move the responsibilities of managing the entity store from the file_transfer_service to the entity_manager, forwarding HTTP entity registration to the latter.

/// Creates a entity metadata for the main device.
pub fn main_device(device_id: String) -> Self {
Self {
topic_id: EntityTopicId::default_main_device(),
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.

This is out-of-scope of this PR, but we must really find a way to support non default topic-id schema.

}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EntityMetadata {
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.

There are now two slightly different definitions of struct EntityMetadata; the former definition has been kept in entity_store.rs.

What's the plan?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

As mentioned in #3230 (comment), the entity store and entity cache needs to maintain their own versions of entity metadata as the latter would be much lighter with minimal metadata maintained at the mapper level. Ideally the EntityMetadata maintained by the mapper should have been as minimal as the XID. But, I was forced to store a bit more info like the entity type, display name and display type just because of the way we map service health status messages by publishing the service creation message itself(which requires all that metadata) for status updates as well. One way to eliminate caching this additional metadata at the mapper level is by making it query the entity store contents from the agent, whenever it requires all that metadata. But that extra HTTP call during the mapping complicates the conversion logic and I just chose caching extra metadata instead of that added complexity. But, open to revisit that decision in a follow-up PR dedicated for that change as the unit test impact would be quite big.

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.

But that extra HTTP call during the mapping complicates the conversion logic and I just chose caching extra metadata instead of that added complexity.

Agree, caching registration messages is simpler than late-requests to the entity store.

But could we share the type of cached data? Say raw registration messages? Even if some fields are not currently used in the mapper.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But could we share the type of cached data? Say raw registration messages? Even if some fields are not currently used in the mapper.

Yeah, that is an option. I introduced a different struct to clearly represent the minimal set of things that a mapper would need to do the mapping. And also, there were minor things like the external id (@id) being an Option in the actual EntityRegistrationMessage, but the same being a mandatory field in the entity cache. But yeah, if we want to avoid having too many "metadata representations" across the crates, I can reuse some of the existing ones with implicit assumptions about fields like @id.

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.

We really have to reduce the number of similar but different structs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Resolved by 8751a76 . Even though a single struct is easier to maintain, I'm still tempted to introduce a dedicated EntityMetadataDto struct to capture the message payloads, without overloading this internal EntityMetadata representation with serde aspects. By using the same struct for everything, I'm a bit worried that it'll make future changes to this internal metadata representation more difficult as it'd affect the external representation as well.

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 don't fully get your concerns.

  • The extra lines for serde are minimal and only related to naming.
  • Is this really using the same struct for everything? These metadata are exchanged over MQTT and stored in-memory. What's wrong?

@albinsuresh
Copy link
Copy Markdown
Contributor Author

I confirm that there are many points to be fixed. None are catastrophic but as whole the feature is not ready.

Differences with the plan

Compared to the design docs:

  • Neither PATCH nor PUT are supported
  • Querying entities with curl '/v1/entities is not implemented

That's okay for this PR, but the query interface would be really handy for testing.

The implementation of PUT and PATCH has been deferred to a follow-up PR as discussed offline.

Weird log entry

Auto-registration of a child device leads to a weird log entry:

Fixed.

Unhelpful error messages on delete

Deleting a child device works:
But both the agent and the mapper emit unhelpful error messages:

On the agent:

2025-01-14T16:02:52.68266318Z ERROR tedge_agent::entity_manager::server: Failed to update entity store with [te/device/child01// qos=1]

and on the mapper:

2025-01-14T15:41:08.937846187Z ERROR c8y_mapper_ext::converter: Mapping error: Unexpected error: Invalid entity registration message received on topic: te/device/child01//

Fixed by properly handling the MQTT "clear" messages published by the agent, which are re-delivered to the agent and the mapper after a successful deletion over HTTP.

Mandatory properties

It's surprising that the topic identifier of entity has to be provided twice.

It's required on the topic:
and as a property:
leading to surprises!

The POST request handler was updated to accept the topic id only via the payload and not via the URL path.

@didier-wenzek didier-wenzek dismissed their stale review January 16, 2025 15:55

The issues have been fixed.

Copy link
Copy Markdown
Contributor

@didier-wenzek didier-wenzek left a comment

Choose a reason for hiding this comment

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

This PR can be merged once renamed the file_transfer_server module.

Thank you for the sustained effort!

Required follow-up tasks:

  • PUT and PATCH implementation
  • Query over registered entities
  • Publishing entity properties as twin metadata
  • Propagating entity deletions to the cloud, controlled by a config setting

@reubenmiller reubenmiller added theme:childdevices Theme: Child device related topics theme:entity_store Entity store related functionality labels Jan 16, 2025
@albinsuresh albinsuresh force-pushed the feat/entity-management-http-apis branch from 66827e3 to bcc67e2 Compare January 17, 2025 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

theme:childdevices Theme: Child device related topics theme:entity_store Entity store related functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants