-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make entity store persistent #2428 #2522
Make entity store persistent #2428 #2522
Conversation
7cadda6
to
4315a60
Compare
Codecov Report
Additional details and impacted files
|
Robot Results
|
4315a60
to
771dd42
Compare
771dd42
to
1eee84f
Compare
1eee84f
to
21d5f39
Compare
9029ff4
to
3001ea3
Compare
crates/common/tedge_config/src/tedge_config_cli/tedge_config.rs
Outdated
Show resolved
Hide resolved
/// ); | ||
/// ``` | ||
pub struct EntityStore { | ||
mqtt_schema: MqttSchema, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this is useful to couple the entity store to a schema. The less coupling, the better.
It seems that the schema is used only to store/load EntityTwinMessage
and EntityRegistrationMessage
using their MQTT representation. Why not simply encapsulate these 2 cases under some EntityStoreMessage
enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this was one of the options that I had evaluated in the last PR, as described in this comment. The main reason why I moved away from that PersistentMessage
enum to raw MqttMessage
was to cover the possibility of making more message types persistent in future, especially the ones like measurements that don't have a concrete struct representation.
pub fn load_from_message_log(&mut self) { | ||
info!("Loading the entity store from the log"); | ||
match self.message_log.reader() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be better to transform this method into a function taking mutable references to an entity store and a log of messages; populating the store from these messages.
A bit more involved, but I would also try to persist the entity store from outside, i.e with a function taking the store and the message log. This can be done by using an internal vector of non-persisted-yet messages.
Doing so:
- The entity store will stay a pure data structure with no side effects.
- The load and persist methods can be made async.
- The logic would be simpler avoiding this usage of boolean flags to control in depth when something needs to be persisted or not.
- The coupling to the mqtt_schema could also be removed that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline, this would be deferred for later.
Persisting the raw MQTT messages is a bit opaque:
|
Will update the serialization logic of |
let mut writer = BufWriter::new(file); | ||
|
||
if file_is_empty { | ||
let version = env!("CARGO_PKG_VERSION"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reubenmiller suggested that we use an independent version scheme for this persistence store file format rather than using the tedge version itself, which will make the validations easier in future, even when the same file format is used across multiple releases. So, this will be version 1.0
of the schema. And it will only be updated when there's a breaking change to the schema.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved
// If the file is empty append the version information as a header | ||
let metadata = file.metadata()?; | ||
let file_is_empty = metadata.len() == 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds a bit fragile, at least unusual.
As this is an append-only log of messages - tracking version is a bit more involved. The first messages are not necessarily written by the same version of the software as the following messages.
What is proposed is okay, but the whole log will have to be rewritten if a new format is introduced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My expectation was that it would be better to discard the log and start fresh if there is a major version mismatch between the version expected by the software and the file read from the disk. Even though I've defined a minor version as well, I don't really have a clear plan on when that would change, keeping the formats compatible between those minor versions. TBH I've only thought about breaking major version changes and kept the minor version number just to enable any possibilities in future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My expectation was that it would be better to discard the log and start fresh if there is a major version mismatch between the version expected by the software and the file read from the disk.
It's why I don't bother to much to have something simple for now - even if a bit fragile.
Even though I've defined a minor version as well, I don't really have a clear plan on when that would change, keeping the formats compatible between those minor versions. TBH I've only thought about breaking major version changes and kept the minor version number just to enable any possibilities in future.
Yeah, this sounds premature, but this is also harmless. So let's go with that for the rc.
Persist the entity store as a JSON lines file. Every registration message and twin data message is persisted as JSON lines. On startup the in-memory entity store is rebuilt by replaying these messages.
b4373da
to
93c0cda
Compare
Test PlanThe externally visible effects of this work are the following:
|
QA has thoroughly checked the feature and here are the results:
|
Proposed changes
Persist the entity store as a JSON lines file.
Every registration message and twin data message is persisted as JSON lines. On startup the in-memory entity store is rebuilt by replaying these messages.
Types of changes
Paste Link to the issue
Checklist
cargo fmt
as mentioned in CODING_GUIDELINEScargo clippy
as mentioned in CODING_GUIDELINESFurther comments