-
Notifications
You must be signed in to change notification settings - Fork 18
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
Add GetValue and GetValues Support #75
Add GetValue and GetValues Support #75
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feature/databroker-api-v2 #75 +/- ##
============================================================
Coverage ? 53.18%
============================================================
Files ? 33
Lines ? 13675
Branches ? 0
============================================================
Hits ? 7273
Misses ? 6402
Partials ? 0 ☔ View full report in Codecov by Sentry. |
@@ -45,7 +45,10 @@ impl From<&proto::Datapoint> for broker::Datapoint { | |||
impl From<broker::Datapoint> for Option<proto::Datapoint> { | |||
fn from(from: broker::Datapoint) -> Self { | |||
match from.value { | |||
broker::DataValue::NotAvailable => None, | |||
broker::DataValue::NotAvailable => Some(proto::Datapoint { |
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 one is worth discussing. Previously (for V2) we just ignored "NotAvailable", i.e. it was never returned in subscribe. But at lest for GetValue we want to return it, so I move the filtering higher up.
But how do we want it to work for Subscribe? If we intend to support actively removing a DataPoint by providing a DataPoint with value Null, then maybe we want the subscribe to also have support for returning Null.
And if so, would it not make sense to also return Null in the first request when subscription is started?
(Currently PR does not change behavior for Subscribe)
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.
Discussed among committers - it seems we want None to be returned also for subscribe. I will check how it affects test case and update the PR
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.
Was not part of the discussion but I think there you can see how it returns None
if DataValue::NotAvailable
->
broker::DataValue::NotAvailable => None, |
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.
It returns None
there, but as it returns None
there it means that the value will be discarded (and not sent to client) at https://github.com/eclipse-kuksa/kuksa-databroker/blob/feature/databroker-api-v2/databroker/src/grpc/kuksa_val_v2/val.rs#L638
Thats why we need to create a Datapoint with value None
here.
Now returns value None when subscription started if there are no value present
03493b5
to
098ccd3
Compare
// | ||
// Returns (GRPC error code): | ||
// NOT_FOUND if any of the requested signals doesn't exist. | ||
// PERMISSION_DENIED if access is denied for any of the requested signals. | ||
// | ||
rpc GetValues(GetValuesRequest) returns (GetValuesResponse); |
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.
General question: Do we need to split this as well by GetValuesId' and
GetValues`?
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.
The message SignalID
supports both, so you can use whatever you like with the same RPC call.
(No tests yet)
a1f12c0
to
d54c4fb
Compare
broker::DataValue::NotAvailable => None, | ||
broker::DataValue::NotAvailable => Some(proto::Datapoint { | ||
value: None, | ||
timestamp: None, |
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.
why should it not have a timestamp?
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.
Fo "normal" DataPoints that has a value the timestamp represents the time the databroker registered that value (doesn't it?). In this case Databroker "deep level magic" has no value and provide no timestamp (I think). We could opt for adding current time if we like to show that it was None at Now, but "Now" is the only time we have.
But a good point to dicuss, do we want a timestamp when return Value==None and if so what Timestamp. (Theoretically we could request Databroker to keep track of when a Value change from something to None, but I do not think it do it at the moment)
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.
It actually seems to return something, at least in some cases, so I will see if I can use it
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.
So it returns registration time for the signal for "virgin" signals, we could use that.
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, that's what I thought of and IF the signal provider would go away you would have a timestamp as well.
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.
So it returns registration time for the signal for "virgin" signals, we could use that.
Setting the value to NotAvailable
behaves just like every other value, at least when it comes to sdv.databroker.v1
(and hence it's supported by the core of databroker).
- Setting a value to
20.0
will record the timestamp of when that happened. - Setting a value to
NotAvailable
will record the timestamp of when that happened.
return Err(tonic::Status::permission_denied("Permission denied")) | ||
} | ||
Err(ReadError::PermissionExpired) => { | ||
return Err(tonic::Status::unauthenticated("Unauthenticated")) |
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.
Wouldn't it be beneficial if we tell them in the message "Unauthenticated because your token expired"?
Err(ReadError::PermissionExpired) => {
return Err(tonic::Status::unauthenticated(format!(
"Permission expired (id: {})",
signal_id
)))
like here in line 120 ff.
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.
Should the Unauthenticated
status also be added to the GetValue
service documentation in the proto file?
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.
Makes sens to say that auth expired.
There are theoretically a lot of GRPC error codes (see for example https://grpc.github.io/grpc/cpp/md_doc_statuscodes.html) that we cannot control but the client still can receive. But it might be a good policy to mention all that we explicitly return in our implementation
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.
Looks good to me, thanks for the documenting the proto files and thanks a lot for adding those really nice unit tests :)
return Err(tonic::Status::permission_denied("Permission denied")) | ||
} | ||
Err(ReadError::PermissionExpired) => { | ||
return Err(tonic::Status::unauthenticated("Unauthenticated")) |
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.
Should the Unauthenticated
status also be added to the GetValue
service documentation in the proto file?
.first_exist() | ||
.request_first() | ||
.send_auth() | ||
.auth_first() |
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.
If auth_first
or auth_second
are set to True
should not be send_auth
True
by default?
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.
Well, at least there is no reason to have auth_first as True if you do not intend to send it. There are generally four combos I check:
- We do not send credentials at all
- We send credentials but they are empty
- We send credentials for signal 1
- We send credentials for signal 2
- We send credentials for signal 1 and 2
I can change so that send_auth
becomes optional if you call one of the other
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.
Maybe then leave it as it is, is not a hurdle to call send_auth
if auth_first
or auth_second
are set to True
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.
You changed it already, thanks
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.
Tested using the following commands:
ghz --insecure --skipFirst 100 --total 100100 --proto ./proto/kuksa/val/v2/val.proto --call kuksa.val.v2.VAL.GetValue -d '{"signal_id": {"path": "Vehicle.Speed"}}' 0.0.0.0:55556
Summary:
Count: 100000
Total: 8.96 s
Slowest: 17.98 ms
Fastest: 0.18 ms
Average: 4.20 ms
Requests/sec: 11159.41
Response time histogram:
0.177 [1] |
1.958 [4235] |∎∎∎
3.738 [25572] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
5.519 [57218] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
7.299 [11867] |∎∎∎∎∎∎∎∎
9.080 [922] |∎
10.860 [93] |
12.641 [52] |
14.421 [37] |
16.202 [1] |
17.982 [2] |
Latency distribution:
10 % in 2.50 ms
25 % in 3.53 ms
50 % in 4.25 ms
75 % in 4.72 ms
90 % in 5.84 ms
95 % in 6.51 ms
99 % in 7.36 ms
Status code distribution:
[OK] 100000 responses
ghz --insecure --skipFirst 100 --total 100100 --proto ./proto/kuksa/val/v2/val.proto --call kuksa.val.v2.VAL.GetValue -d '{"signal_id": {"id": 100}}' 0.0.0.0:55556
Summary:
Count: 100000
Total: 8.68 s
Slowest: 12.33 ms
Fastest: 0.15 ms
Average: 4.07 ms
Requests/sec: 11525.19
Response time histogram:
0.151 [1] |
1.368 [1093] |∎
2.586 [10441] |∎∎∎∎∎∎∎∎
3.803 [23750] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
5.021 [49185] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
6.238 [10316] |∎∎∎∎∎∎∎∎
7.456 [4902] |∎∎∎∎
8.673 [203] |
9.891 [52] |
11.108 [23] |
12.326 [34] |
Latency distribution:
10 % in 2.46 ms
25 % in 3.42 ms
50 % in 4.14 ms
75 % in 4.59 ms
90 % in 5.58 ms
95 % in 6.27 ms
99 % in 7.02 ms
Status code distribution:
[OK] 100000 responses
ghz --insecure --skipFirst 100 --total 100100 --proto ./proto/kuksa/val/v2/val.proto --call kuksa.val.v2.VAL.GetValues -d '{"signal_ids": [{"path": "Vehicle.Speed"},{"path": "Vehicle.ADAS.ABS.IsEnabled"},{"id": 100}]}' 0.0.0.0:55556
Summary:
Count: 100000
Total: 8.90 s
Slowest: 19.57 ms
Fastest: 0.19 ms
Average: 4.18 ms
Requests/sec: 11241.01
Response time histogram:
0.194 [1] |
2.131 [5680] |∎∎∎∎
4.068 [34113] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
6.005 [52709] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
7.942 [7293] |∎∎∎∎∎∎
9.880 [111] |
11.817 [43] |
13.754 [0] |
15.691 [0] |
17.629 [4] |
19.566 [46] |
Latency distribution:
10 % in 2.54 ms
25 % in 3.58 ms
50 % in 4.25 ms
75 % in 4.69 ms
90 % in 5.68 ms
95 % in 6.37 ms
99 % in 7.14 ms
Status code distribution:
[OK] 100000 responses
Also tested the error case, where invalid VSS Paths or invalid ids are used.
Performance-wise it looks comparable to kuksa.val.v1.Get:
ghz --insecure --skipFirst 100 --total 100100 --proto ./proto/kuksa/val/v1/val.proto --call kuksa.val.v1.VAL.Get -d '{"entries": {"path": "Vehicle.Speed", "view": 1, "fields": 2}}' 0.0.0.0:55556
Summary:
Count: 100000
Total: 9.97 s
Slowest: 16.46 ms
Fastest: 0.52 ms
Average: 4.72 ms
Requests/sec: 10030.76
Response time histogram:
0.519 [1] |
2.113 [1758] |∎
3.706 [13936] |∎∎∎∎∎∎∎∎∎
5.300 [60628] |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
6.894 [18435] |∎∎∎∎∎∎∎∎∎∎∎∎
8.488 [4938] |∎∎∎
10.081 [242] |
11.675 [51] |
13.269 [10] |
14.863 [0] |
16.457 [1] |
Latency distribution:
10 % in 3.19 ms
25 % in 4.15 ms
50 % in 4.72 ms
75 % in 5.26 ms
90 % in 6.22 ms
95 % in 6.93 ms
99 % in 7.86 ms
Status code distribution:
[OK] 100000 responses
Behavior is correct, therefore LGTM
Thanks for testing @wba2hi |
435e88f
into
eclipse-kuksa:feature/databroker-api-v2
* Add GetValue and GetValues Support
* Add GetValue and GetValues Support
* Add GetValue and GetValues Support
* Add GetValue and GetValues Support
* Add GetValue and GetValues Support
No description provided.