From 59265ab334fc42f56c17259d14758e457def353d Mon Sep 17 00:00:00 2001 From: Rafael RL Date: Thu, 24 Oct 2024 15:44:08 +0200 Subject: [PATCH] Update incomplete information on errors --- .../src/grpc/kuksa_val_v2/conversions.rs | 6 +- databroker/src/grpc/kuksa_val_v2/val.rs | 240 ++++++------------ proto/kuksa/val/v2/val.proto | 57 ++++- 3 files changed, 127 insertions(+), 176 deletions(-) diff --git a/databroker/src/grpc/kuksa_val_v2/conversions.rs b/databroker/src/grpc/kuksa_val_v2/conversions.rs index a2262d81..fe7ce586 100644 --- a/databroker/src/grpc/kuksa_val_v2/conversions.rs +++ b/databroker/src/grpc/kuksa_val_v2/conversions.rs @@ -456,11 +456,11 @@ impl broker::UpdateError { format!("Wrong type provided (id: {})", id), ), broker::UpdateError::OutOfBounds => tonic::Status::new( - tonic::Code::OutOfRange, + tonic::Code::InvalidArgument, format!("Value out of bounds (id: {})", id), ), broker::UpdateError::UnsupportedType => tonic::Status::new( - tonic::Code::Unimplemented, + tonic::Code::InvalidArgument, format!("Unsupported type (id: {})", id), ), broker::UpdateError::PermissionDenied => tonic::Status::new( @@ -610,7 +610,7 @@ impl broker::ActuationError { match self { broker::ActuationError::NotFound => tonic::Status::not_found(message), broker::ActuationError::WrongType => tonic::Status::invalid_argument(message), - broker::ActuationError::OutOfBounds => tonic::Status::out_of_range(message), + broker::ActuationError::OutOfBounds => tonic::Status::invalid_argument(message), broker::ActuationError::UnsupportedType => tonic::Status::invalid_argument(message), broker::ActuationError::PermissionDenied => tonic::Status::permission_denied(message), broker::ActuationError::PermissionExpired => tonic::Status::unauthenticated(message), diff --git a/databroker/src/grpc/kuksa_val_v2/val.rs b/databroker/src/grpc/kuksa_val_v2/val.rs index d6026e1a..4e3ffdfe 100644 --- a/databroker/src/grpc/kuksa_val_v2/val.rs +++ b/databroker/src/grpc/kuksa_val_v2/val.rs @@ -90,6 +90,11 @@ impl ActuationProvider for Provider { #[tonic::async_trait] impl proto::val_server::Val for broker::DataBroker { + // Returns (GRPC error code): + // NOT_FOUND if the requested signal doesn't exist + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied + // async fn get_value( &self, request: tonic::Request, @@ -128,6 +133,11 @@ impl proto::val_server::Val for broker::DataBroker { })) } + // Returns (GRPC error code): + // NOT_FOUND if any of the requested signals doesn't exist. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied for any of the requested signals. + // async fn get_values( &self, request: tonic::Request, @@ -192,7 +202,12 @@ impl proto::val_server::Val for broker::DataBroker { + 'static, >, >; - + // Returns (GRPC error code): + // NOT_FOUND if any of the signals are non-existant. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied for any of the signals. + // INVALID_ARGUMENT if the request is empty or provided path is too long + // async fn subscribe( &self, request: tonic::Request, @@ -253,7 +268,12 @@ impl proto::val_server::Val for broker::DataBroker { + 'static, >, >; - + // Returns (GRPC error code): + // NOT_FOUND if any of the signals are non-existant. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // PERMISSION_DENIED if access is denied for any of the signals. + // INVALID_ARGUMENT if the request is empty + // async fn subscribe_by_id( &self, request: tonic::Request, @@ -311,17 +331,19 @@ impl proto::val_server::Val for broker::DataBroker { } } - // Actuate a single actuator - // // Returns (GRPC error code): // NOT_FOUND if the actuator does not exist. // PERMISSION_DENIED if access is denied for the actuator. + // UNAUTHENTICATED if no credentials provided or credentials has expired // UNAVAILABLE if there is no provider currently providing the actuator + // DATA_LOSS is there is a internal TransmissionFailure // INVALID_ARGUMENT // - if the data type used in the request does not match // the data type of the addressed signal // - if the requested value is not accepted, // e.g. if sending an unsupported enum value + // - if the provided value is out of the min/max range specified + // async fn actuate( &self, request: tonic::Request, @@ -378,12 +400,16 @@ impl proto::val_server::Val for broker::DataBroker { // Returns (GRPC error code): // NOT_FOUND if any of the actuators are non-existant. // PERMISSION_DENIED if access is denied for any of the actuators. + // UNAUTHENTICATED if no credentials provided or credentials has expired // UNAVAILABLE if there is no provider currently providing an actuator + // DATA_LOSS is there is a internal TransmissionFailure // INVALID_ARGUMENT // - if the data type used in the request does not match // the data type of the addressed signal // - if the requested value is not accepted, // e.g. if sending an unsupported enum value + // - if any of the provided actuators values are out of the min/max range specified + // async fn batch_actuate( &self, request: tonic::Request, @@ -437,33 +463,11 @@ impl proto::val_server::Val for broker::DataBroker { } } - /// List metadata of signals matching the wildcard branch request. - /// - /// # Arguments - /// - /// ``` - /// `request`: - /// ListMetadataRequest { - /// root: String - /// filter: String - /// } - /// - /// # Response - /// `response`: - /// ListMetadataResponse { - /// metadata: Vec - /// } - /// ``` - /// - /// # Errors - /// - /// Returns (GRPC error code): - /// NOT_FOUND if the specified root branch does not exist - /// INVALID_ARGUMENT if the request pattern is invalid - /// - /// # Examples - /// For details, please refer to - /// [Wildcard Matching](https://github.com/eclipse-kuksa/kuksa-databroker/blob/main/doc/wildcard_matching.md#examples) + // Returns (GRPC error code): + // NOT_FOUND if the specified root branch does not exist. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // INVALID_ARGUMENT if the provided path or wildcard is wrong. + // async fn list_metadata( &self, request: tonic::Request, @@ -505,34 +509,18 @@ impl proto::val_server::Val for broker::DataBroker { } } - // Publish a signal value. Used for low frequency signals (e.g. attributes). - /// # Arguments - /// - /// ``` - /// `request`: - /// PublishValueRequest { - /// signal_id: - /// datapoint: Datapoint - /// } - /// - /// # Response - /// `response`: - /// PublishValueResponse { - /// error: Error - /// } - /// ``` - /// - /// # Errors - /// Returns (GRPC error code): - /// NOT_FOUND if any of the signals are non-existant. - /// PERMISSION_DENIED - /// - if access is denied for any of the signals. - /// - if the signal is already provided by another provider. - /// INVALID_ARGUMENT - /// - if the data type used in the request does not match - /// the data type of the addressed signal - /// - if the published value is not accepted, - /// e.g. if sending an unsupported enum value + // Returns (GRPC error code): + // NOT_FOUND if any of the signals are non-existant. + // PERMISSION_DENIED + // - if access is denied for any of the signals. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // INVALID_ARGUMENT + // - if the data type used in the request does not match + // the data type of the addressed signal + // - if the published value is not accepted, + // e.g. if sending an unsupported enum value + // - if the published value is out of the min/max range specified + // async fn publish_value( &self, request: tonic::Request, @@ -587,113 +575,33 @@ impl proto::val_server::Val for broker::DataBroker { } } - // type OpenProviderStreamStream = Pin< - // Box< - // dyn Stream> - // + Send - // + Sync - // + 'static, - // >, - // >; - type OpenProviderStreamStream = ReceiverStream>; - /// Opens a bidirectional stream with the databroker to perform various actions such as - /// providing actuators, publishing sensor and actuator values, and receiving actuations from the databroker. - /// - /// # Actions - /// - /// The function handles the following actions: - /// - /// 1. **Provide an Actuator**: - /// - The provider claims ownership of the actuator with the specified signal ID. - /// - /// ``` - /// `request`: - /// OpenProviderStreamRequest { - /// action: ProvideActuationRequest { - /// { - /// signal: id: 30, - /// }, - /// { - /// signal: id: 45, - /// }, - /// ... - /// } - /// } - /// - /// `response`: - /// OpenProviderStreamStream { - /// action: ProvideActuattionResponse { } - /// } - /// ``` - /// - /// 2. **Publish Values**: - /// - The provider publishes a request ID along with a map of sensor and actuator values. - /// - /// ``` - /// `request`: - /// OpenProviderStreamRequest { - /// action: PublishValuesRequest { - /// request_id: 1, - /// datapoints: { - /// (30, Datapoint), - /// (45, Datapoint), - /// ... - /// } - /// } - /// } - /// - /// `response`: - /// OpenProviderStreamStream { - /// action: PublishValuesResponse { - /// request_id: 1, - /// status: { - /// (If errors) { - /// (30, Error), - /// (45, Error), - /// ... - /// } - /// } - /// } - /// } - /// ``` - /// - /// 3. **Receive Actuations**: - /// - The provider receives actuation requests from the databroker. - /// - /// ``` - /// `request`: - /// OpenProviderStreamRequest { - /// action: BatchActuateStreamResponse { } - /// } - /// - /// `response`: - /// OpenProviderStreamStream { - /// action: BatchActuateStreamRequest { - /// actuate_requests: { - /// (30, Value), - /// (45, Value), - /// ... - /// } - /// } - /// } - /// ``` - /// - /// # Arguments - /// - /// * `request` - The request should contain the necessary permissions if the databroker is started with secure mode. - /// The request `OpenProviderStreamRequest` can contain messages according to the action: - /// - Action 1: `ProvideActuationRequest` - /// - Action 2: `PublishValuesRequest` - /// - Action 3: `BatchActuateStreamResponse` - /// - /// # Errors - /// - /// The open stream is used for request / response type communication between the - /// provider and server (where the initiator of a request can vary). - /// Errors are communicated as messages in the stream. + // Errors: + // - Provider sends ProvideActuationRequest -> Databroker returns ProvideActuationResponse + // Returns (GRPC error code) and closes the stream call (strict case). + // NOT_FOUND if any of the signals are non-existant. + // PERMISSION_DENIED if access is denied for any of the signals. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // ALREADY_EXISTS if a provider already claimed the ownership of an actuator + // + // - Provider sends PublishValuesRequest -> Databroker returns PublishValuesResponse + // GRPC errors are returned as messages in the stream + // response with the signal id `map status = 2;` (permissive case) + // NOT_FOUND if a signal is non-existant. + // PERMISSION_DENIED + // - if access is denied for a signal. + // INVALID_ARGUMENT + // - if the data type used in the request does not match + // the data type of the addressed signal + // - if the published value is not accepted, + // e.g. if sending an unsupported enum value + // - if the published value is out of the min/max range specified + // + // - Provider returns BatchActuateStreamResponse <- Databroker sends BatchActuateStreamRequest + // No error definition, a BatchActuateStreamResponse is expected from provider. + // async fn open_provider_stream( &self, request: tonic::Request>, @@ -707,10 +615,6 @@ impl proto::val_server::Val for broker::DataBroker { None => return Err(tonic::Status::unauthenticated("Unauthenticated")), }; - // Should databroker register internally here new opened streams???? - // The provided actuation will take ownership over the actuators but what happens - // if a provider is publishing sensor values and the stream is closed? - // How will the application know that there is no provider and should stop the subscription? let mut stream = request.into_inner(); let mut shutdown_trigger = self.get_shutdown_trigger(); @@ -1806,7 +1710,7 @@ mod tests { } Err(status) => { // Handle the error from the publish_value function - assert_eq!(status.code(), tonic::Code::OutOfRange); + assert_eq!(status.code(), tonic::Code::InvalidArgument); // As of the today the first added datapoint get value 0 by default. assert_eq!(status.message(), "Value out of bounds (id: 0)"); } diff --git a/proto/kuksa/val/v2/val.proto b/proto/kuksa/val/v2/val.proto index fa91efb6..f282a228 100644 --- a/proto/kuksa/val/v2/val.proto +++ b/proto/kuksa/val/v2/val.proto @@ -45,17 +45,27 @@ service VAL { // Subscribe to a set of signals using string path parameters // Returns (GRPC error code): // NOT_FOUND if any of the signals are non-existant. + // UNAUTHENTICATED if no credentials provided or credentials has expired // PERMISSION_DENIED if access is denied for any of the signals. + // INVALID_ARGUMENT if the request is empty or provided path is too long + // + // When subscribing, Databroker shall immediately return the value for all + // subscribed entries. + // If a value isn't available when subscribing to a it, it should return None // - // When subscribing the Broker shall immediately return the value for all - // subscribed entries. If no value is available when subscribing a DataPoint - // with value None shall be returned. rpc Subscribe(SubscribeRequest) returns (stream SubscribeResponse); // Subscribe to a set of signals using i32 id parameters // Returns (GRPC error code): // NOT_FOUND if any of the signals are non-existant. + // UNAUTHENTICATED if no credentials provided or credentials has expired // PERMISSION_DENIED if access is denied for any of the signals. + // INVALID_ARGUMENT if the request is empty + // + // When subscribing, Databroker shall immediately return the value for all + // subscribed entries. + // If a value isn't available when subscribing to a it, it should return None + // rpc SubscribeById(SubscribeByIdRequest) returns (stream SubscribeByIdResponse); // Actuate a single actuator @@ -63,12 +73,16 @@ service VAL { // Returns (GRPC error code): // NOT_FOUND if the actuator does not exist. // PERMISSION_DENIED if access is denied for the actuator. + // UNAUTHENTICATED if no credentials provided or credentials has expired // UNAVAILABLE if there is no provider currently providing the actuator + // DATA_LOSS is there is a internal TransmissionFailure // INVALID_ARGUMENT // - if the data type used in the request does not match // the data type of the addressed signal // - if the requested value is not accepted, // e.g. if sending an unsupported enum value + // - if the provided value is out of the min/max range specified + // rpc Actuate(ActuateRequest) returns (ActuateResponse); // Actuate simultaneously multiple actuators. @@ -78,18 +92,25 @@ service VAL { // Returns (GRPC error code): // NOT_FOUND if any of the actuators are non-existant. // PERMISSION_DENIED if access is denied for any of the actuators. + // UNAUTHENTICATED if no credentials provided or credentials has expired // UNAVAILABLE if there is no provider currently providing an actuator + // DATA_LOSS is there is a internal TransmissionFailure // INVALID_ARGUMENT // - if the data type used in the request does not match // the data type of the addressed signal // - if the requested value is not accepted, // e.g. if sending an unsupported enum value + // - if any of the provided actuators values are out of the min/max range specified + // rpc BatchActuate(BatchActuateRequest) returns (BatchActuateResponse); // List metadata of signals matching the request. // // Returns (GRPC error code): // NOT_FOUND if the specified root branch does not exist. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // INVALID_ARGUMENT if the provided path or wildcard is wrong. + // rpc ListMetadata(ListMetadataRequest) returns (ListMetadataResponse); // Publish a signal value. Used for low frequency signals (e.g. attributes). @@ -98,12 +119,14 @@ service VAL { // NOT_FOUND if any of the signals are non-existant. // PERMISSION_DENIED // - if access is denied for any of the signals. - // - if the signal is already provided by another provider. + // UNAUTHENTICATED if no credentials provided or credentials has expired // INVALID_ARGUMENT // - if the data type used in the request does not match // the data type of the addressed signal // - if the published value is not accepted, // e.g. if sending an unsupported enum value + // - if the published value is out of the min/max range specified + // rpc PublishValue(PublishValueRequest) returns (PublishValueResponse); // Open a stream used to provide actuation and/or publishing values using @@ -112,7 +135,31 @@ service VAL { // // The open stream is used for request / response type communication between the // provider and server (where the initiator of a request can vary). - // Errors are communicated as messages in the stream. + // + // Errors: + // - Provider sends ProvideActuationRequest -> Databroker returns ProvideActuationResponse + // Returns (GRPC error code) and closes the stream call (strict case). + // NOT_FOUND if any of the signals are non-existant. + // PERMISSION_DENIED if access is denied for any of the signals. + // UNAUTHENTICATED if no credentials provided or credentials has expired + // ALREADY_EXISTS if a provider already claimed the ownership of an actuator + // + // - Provider sends PublishValuesRequest -> Databroker returns PublishValuesResponse + // GRPC errors are returned as messages in the stream + // response with the signal id `map status = 2;` (permissive case) + // NOT_FOUND if a signal is non-existant. + // PERMISSION_DENIED + // - if access is denied for a signal. + // INVALID_ARGUMENT + // - if the data type used in the request does not match + // the data type of the addressed signal + // - if the published value is not accepted, + // e.g. if sending an unsupported enum value + // - if the published value is out of the min/max range specified + // + // - Provider returns BatchActuateStreamResponse <- Databroker sends BatchActuateStreamRequest + // No error definition, a BatchActuateStreamResponse is expected from provider. + // rpc OpenProviderStream(stream OpenProviderStreamRequest) returns (stream OpenProviderStreamResponse); // Get server information