Refactor: Simplify entity auto-registration#3139
Refactor: Simplify entity auto-registration#3139didier-wenzek merged 2 commits intothin-edge:mainfrom
Conversation
| parent: None, | ||
| parent: Some(EntityTopicId::from_str("device/main//").unwrap()), |
There was a problem hiding this comment.
I was surprised by this. Why the parent of child device was expected to be None? Because no registration is required for the main device?
There was a problem hiding this comment.
EntityRegistrationMessage is supposed to be a subtype of MqttMessage, but with required fields like type or external_id present. Because it was supposed to be only created by converting from MqttMessage, it was to have only the same information that MqttMessage had, and actual filling of fallbacks and defaults was to be done in entity store when adding the entity (because only the entity store knows what's the actual name of main device and has a function to generate the entity's external id).
So in this case MqttMessage payload that contained no parent field would be converted to EntityRegistrationMessage that didn't contain it as well, and the parent would be resolved by the entity store when registering the child.
So I think it'd be better to leave it as None.
There was a problem hiding this comment.
and the parent would be resolved by the entity store when registering the child.
This is what I would like to fix with this PR. Indeed, for auto registration, the entity store starts with a topic matching the default topic scheme (starting with a validation) and then extracts sub data (type, names, relationship) using misc functions assuming each the default topic scheme.
With this PR, the entity store can parse an entity topic id into all the info required for auto-registration is applicable.
This also addresses what you noted : currently it seems it has a very large surface with lots of methods that are ultimately a bit shallow
There was a problem hiding this comment.
So I think it'd be better to leave it as None.
However, I will opt for the other way, i.e. setting the parent. Indeed, the point of the parse(entity_topic_id)
is to provide an explicit representation of all what is implied by an entity topic of the default topic scheme.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files📢 Thoughts on this report? Let us know! |
Robot Results
|
879ede2 to
c1e76fa
Compare
Bravo555
left a comment
There was a problem hiding this comment.
Seems a small simplification with no functional changes, approving with a small comment regarding the changed unit test.
But I'm reminded how entity store and entity topic id logic could be made simpler, as currently it seems it has a very large surface with lots of methods that are ultimately a bit shallow.
| ["device", child, "service", service] if !child.is_empty() && !service.is_empty() => { | ||
| // The device of a service has to be registered fist | ||
| let child_topic_id = EntityTopicId::default_child_device(child).unwrap(); | ||
| let mut registrations = parse(&child_topic_id); | ||
|
|
||
| // Then the service can be registered | ||
| registrations.push(EntityRegistrationMessage { | ||
| topic_id: topic_id.clone(), | ||
| external_id: None, | ||
| r#type: EntityType::Service, | ||
| parent: Some(EntityTopicId::default_child_device(child).unwrap()), | ||
| other: json!({ "name": service }).as_object().unwrap().to_owned(), | ||
| }); | ||
| registrations | ||
| } |
There was a problem hiding this comment.
suggestion: this branch also covers the case when child = "main", so service for the main device, perhaps rename child to device to make it more clear
There was a problem hiding this comment.
Or even a dedicated arm for the main device service case, as the parent (main device) need not be registered in that case.
| if auto_entity.r#type == EntityType::Service { | ||
| auto_entity | ||
| .other | ||
| .insert("type".to_string(), self.default_service_type.clone().into()); | ||
| } |
There was a problem hiding this comment.
thought: Bit awkward we still need this branch here because c8y needs to have a service type, which I reckon doesn't have much use in a local entity store, but we only have access to fallback default service type in the entity store.
In the future it'd be good to move it either up to c8y mapper (I think it was there before, but can't remember the reason why I pulled it into the entity store, perhaps I was wrong to do so) or down somewhere, but in any case it feels kind of out of place in here.
| parent: None, | ||
| parent: Some(EntityTopicId::from_str("device/main//").unwrap()), |
There was a problem hiding this comment.
EntityRegistrationMessage is supposed to be a subtype of MqttMessage, but with required fields like type or external_id present. Because it was supposed to be only created by converting from MqttMessage, it was to have only the same information that MqttMessage had, and actual filling of fallbacks and defaults was to be done in entity store when adding the entity (because only the entity store knows what's the actual name of main device and has a function to generate the entity's external id).
So in this case MqttMessage payload that contained no parent field would be converted to EntityRegistrationMessage that didn't contain it as well, and the parent would be resolved by the entity store when registering the child.
So I think it'd be better to leave it as None.
albinsuresh
left a comment
There was a problem hiding this comment.
The refactoring looks fine to me. Yet there are some test failures.
| .default_source_device_identifier() | ||
| .expect("device id must be present as the topic id follows the default scheme"); | ||
|
|
||
| if !parent_device_id.is_default_main_device() && self.get(&parent_device_id).is_none() { |
There was a problem hiding this comment.
Oops, I removed this check that the device should not already be registered.
self.get(&parent_device_id).is_none()
This explains why the system tests are failing.
Before, only the service where registered:
c8y/s/us/foo_child1 102,foo:device:foo_child1:service:app1,service,app1,up
But this check missing service is also registered, while already known by c8y:
c8y/s/us 101,foo:device:foo_child1,foo_child1,thin-edge.io-child
c8y/s/us/foo_child1 102,foo:device:foo_child1:service:app1,service,app1,up
Introduce a new function `mqtt_topic::default_topic_schema::parse()` taking an entity topic id and returning the registration messages matching the auto-registration behavior. Using this parse function simplifies the auto-registration logic which has no more to parse again and again the entity topic id to extract registration info. Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
Signed-off-by: Didier Wenzek <didier.wenzek@free.fr>
cde04b7 to
7b71d09
Compare
Proposed changes
Introduce a new function
mqtt_topic::default_topic_schema::parse()taking an entity topic id and returning the registration messages matching the auto-registration behavior.Using this
parsefunction simplifies the auto-registration logic which has no more to parse again and again the entity topic id to extract registration info.Types of changes
Paste Link to the issue
Checklist
cargo fmtas mentioned in CODING_GUIDELINEScargo clippyas mentioned in CODING_GUIDELINESFurther comments