Skip to content
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

Create a ClientTrait for RustSDK #142

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

lukasmittag
Copy link
Contributor

For handling the Rust SDK and preparing to make it an own crate this introduces a ClientTrait. With this the maintenance of the soon-to-be Rust SDK will be easy and manageable.

@lukasmittag lukasmittag force-pushed the feature/rust_sdk_client_trait branch from 46bd034 to ddbc538 Compare February 26, 2025 10:24
@lukasmittag lukasmittag force-pushed the feature/rust_sdk_client_trait branch from ddbc538 to bae6f53 Compare February 26, 2025 10:27
Copy link

codecov bot commented Feb 26, 2025

Codecov Report

Attention: Patch coverage is 17.52988% with 207 lines in your changes missing coverage. Please review.

Project coverage is 59.47%. Comparing base (c8c1a60) to head (df25af6).

Files with missing lines Patch % Lines
databroker-cli/src/kuksa_cli.rs 0.00% 90 Missing ⚠️
lib/sdv/src/lib.rs 0.00% 65 Missing ⚠️
lib/kuksa/src/lib.rs 46.31% 51 Missing ⚠️
databroker-cli/src/sdv_cli.rs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #142      +/-   ##
==========================================
+ Coverage   59.38%   59.47%   +0.09%     
==========================================
  Files          34       34              
  Lines       15137    15085      -52     
==========================================
- Hits         8989     8972      -17     
+ Misses       6148     6113      -35     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@wba2hi wba2hi left a comment

Choose a reason for hiding this comment

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

no functional test has been done yet.

Comment on lines 112 to 120
type DatapointType = HashMap<String, proto::v1::Datapoint>;
type PathType = Vec<String>;
type SubscribeType = Self::PathType;
type PublishResponseType = ();
type GetResponseType = Vec<DataEntry>;
type SubscribeResponseType = tonic::Streaming<proto::v1::SubscribeResponse>;
type ProvideResponseType = tonic::Streaming<proto::v1::SubscribeResponse>;
type ActuateResponseType = ();
type MetadataResponseType = Vec<DataEntry>;
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that the types are closely coupled to the parameters / return values of the corresponding grpc interface methods but right now the types selected here feel arbritrarily chosen and not really fitting to their "type alias".

Maybe this is just a naming thingy and clarity can be increased by making clear what kind of type they are, like ParameterType, ReturnType,...

Like, why is a DatapointType a HashMap<String, Datapoint>? I would more expect like DatapointType to be proto::v1::Datapoint and then somewhere it uses HashMap<String, DatapointType> or similar.
A PathType could be a String, and sometimes (e.g. get) it's simply used as PathType and sometimes (e.g. subscribe) it's used as Vec<PathType>. However I did not play this through if this model would hold for all the implementors (sdv, val.v1, val.v2).

Please think a bit more about how to increase clarity e.g. by renaming the ...Typeor by aligning the implementations.

type MetadataResponseType;

// from deeply embedded layer providing sensor values (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplented error for the function
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// if we do not want to put in the effort just give an unimplented error for the function
// if we do not want to put in the effort just give an unimplemented error for the function

It's a weird suggestion to make :D do we expect anywhere that this would apply, e.g. in sdv? shouldn't we at least make sure for val.v1 and val.v2 that the function set should be similar and implemented (exceptions of course do apply e.g. for the target_value thingies which no longer exist in v2, but maybe this means we shouldn't expose it in ClientTrait anymore?)

If I understood correctly the ClientTrait methods will just call the existing methods, like ClientTrait#publish would call val.v1 set with Field.VALUE while ClientTrait#actuate would call set with Field.TARGET_VALUE

) -> Result<Self::PublishResponseType, ClientError>;

// from application getting sensor values (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplented error for the function
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// if we do not want to put in the effort just give an unimplented error for the function
// if we do not want to put in the effort just give an unimplemented error for the function

Comment on lines 105 to 106
// from povider side pick up actuation requests (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplented error for the function
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// from povider side pick up actuation requests (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplented error for the function
// from provider side: pick up actuation requests (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplemented error for the function

Comment on lines 89 to 90
// from povider side pick up actuation requests (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplented error for the function
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// from povider side pick up actuation requests (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplented error for the function
// from provider side: pick up actuation requests (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplemented error for the function

None
}
};
let datapoint_entries = handle_get_metadata(vec![path], client).await.unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't simply unwrapping the result here crash the application in case of an err? might be a rare case though as this only happens when cli::print_error(...) or prin_resp_err_fm fails - might be neglectable.

@@ -329,20 +331,9 @@ pub async fn kuksa_main(_cli: Cli) -> Result<(), Box<dyn std::error::Error>> {

let pattern = vec!["**"];
Copy link
Contributor

Choose a reason for hiding this comment

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

optional: could be inlined

);
} else {
let name = entry.path.clone();
println!("No entry metadata for {name}");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
println!("No entry metadata for {name}");
println!("No metadata entry for {name}");

&mut self,
paths: Self::PathType,
) -> Result<Self::ProvideResponseType, ClientError> {
println!("Actuation concept has changed with kuksa.val.v2 only supported by it! Defaulting to subscribing to target values.");
Copy link
Contributor

Choose a reason for hiding this comment

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

should the sdk use println! or better one of the log macros, like warn!? mutiple occurrences

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm warn would be more suitable yes.

type MetadataResponseType;

// from deeply embedded layer providing sensor values (to keep backwards compatibility the naming is different for the corresponding interfaces)
// if we do not want to put in the effort just give an unimplemented error for the function
Copy link
Contributor

@rafaeling rafaeling Feb 28, 2025

Choose a reason for hiding this comment

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

Really like the idea of having traits here, just one thing:
what about splitting interfaces? like creating a generic interface which cover common cases from all the APIs like subscribe, publish, etc and an specific traits which covers the target_values use cases, etc?
Something like:
trait GenericSDK { fn subscribe(&self); }
trait TargetValueSDK: GenericSDK { fn set_target_values(&self); }

If I am a sdk user for kuksa_val_v2, it would be confuse to see set_target_values, etc methods

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm yes but I thought a little bit about managing backwards compatibility. For the sdk agree that it looks strange for people. And for now we might not need backwards compatibility. However I will think about generic sdk and additions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants