use core::fmt::Debug;
use azure_iot_operations_mqtt::token::AckToken;
use azure_iot_operations_protocol::{common::aio_protocol_error::AIOProtocolError, rpc_command};
use chrono::{DateTime, Utc};
use thiserror::Error;
use crate::azure_device_registry::helper::ConvertOptionVec;
use crate::azure_device_registry::models::{Asset, Device};
use crate::azure_device_registry::{
adr_base_gen::adr_base_service::client as base_client_gen,
device_discovery_gen::device_discovery_service::client as discovery_client_gen,
};
use crate::common::dispatcher::{self, Receiver};
#[allow(clippy::doc_markdown)] mod adr_base_gen;
mod device_discovery_gen;
pub mod client;
mod helper;
pub mod models;
pub use client::{Client, ClientOptions, ClientOptionsBuilder};
#[derive(Debug, Error)]
#[error(transparent)]
pub struct Error(#[from] ErrorKind);
impl Error {
#[must_use]
pub fn kind(&self) -> &ErrorKind {
&self.0
}
}
#[derive(Error, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum ErrorKind {
#[error(transparent)]
AIOProtocolError(#[from] AIOProtocolError),
#[error(transparent)]
InvalidRequestArgument(#[from] rpc_command::invoker::RequestBuilderError),
#[error("{0:?}")]
ServiceError(base_client_gen::AkriServiceError),
#[error("Device or asset may only be observed once at a time")]
DuplicateObserve(#[from] dispatcher::RegisterError),
#[error("Shutdown error occurred with the following protocol errors: {0:?}")]
ShutdownError(Vec<AIOProtocolError>),
#[error("{0}")]
ValidationError(String),
}
impl From<rpc_command::invoker::Response<base_client_gen::AkriServiceError>> for ErrorKind {
fn from(value: rpc_command::invoker::Response<base_client_gen::AkriServiceError>) -> Self {
Self::ServiceError(value.payload)
}
}
impl From<rpc_command::invoker::Response<discovery_client_gen::AkriServiceError>> for ErrorKind {
fn from(value: rpc_command::invoker::Response<discovery_client_gen::AkriServiceError>) -> Self {
Self::ServiceError(value.payload.into())
}
}
#[derive(Debug)]
pub struct DeviceUpdateObservation(Receiver<(Device, Option<AckToken>)>);
impl DeviceUpdateObservation {
pub async fn recv_notification(&mut self) -> Option<(Device, Option<AckToken>)> {
self.0.recv().await
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct AssetRef {
pub name: String,
pub device_name: String,
pub inbound_endpoint_name: String,
}
#[derive(Debug)]
pub struct AssetUpdateObservation(Receiver<(Asset, Option<AckToken>)>);
impl AssetUpdateObservation {
pub async fn recv_notification(&mut self) -> Option<(Asset, Option<AckToken>)> {
self.0.recv().await
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ConfigStatus {
pub error: Option<ConfigError>,
pub last_transition_time: Option<DateTime<Utc>>,
pub version: Option<u64>,
}
#[derive(Clone, Debug, Default, PartialEq, Error)]
#[error("{}", message.as_deref().unwrap_or("Unknown configuration error"))]
pub struct ConfigError {
pub code: Option<String>,
pub details: Option<Vec<Details>>,
pub message: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Default)]
pub struct Details {
pub code: Option<String>,
pub correlation_id: Option<String>,
pub info: Option<String>,
pub message: Option<String>,
}
impl From<discovery_client_gen::AkriServiceError> for base_client_gen::AkriServiceError {
fn from(value: discovery_client_gen::AkriServiceError) -> Self {
base_client_gen::AkriServiceError {
code: value.code.into(),
message: value.message,
timestamp: value.timestamp,
}
}
}
impl From<discovery_client_gen::CodeSchema> for base_client_gen::CodeSchema {
fn from(value: discovery_client_gen::CodeSchema) -> Self {
match value {
discovery_client_gen::CodeSchema::BadRequest => base_client_gen::CodeSchema::BadRequest,
discovery_client_gen::CodeSchema::InternalError => {
base_client_gen::CodeSchema::InternalError
}
discovery_client_gen::CodeSchema::KubeError => base_client_gen::CodeSchema::KubeError,
discovery_client_gen::CodeSchema::SerializationError => {
base_client_gen::CodeSchema::SerializationError
}
discovery_client_gen::CodeSchema::Unauthorized => {
base_client_gen::CodeSchema::Unauthorized
}
}
}
}
impl From<ConfigStatus> for base_client_gen::ConfigStatus {
fn from(value: ConfigStatus) -> Self {
base_client_gen::ConfigStatus {
error: value.error.map(Into::into),
last_transition_time: value.last_transition_time,
version: value.version,
}
}
}
impl From<base_client_gen::ConfigStatus> for ConfigStatus {
fn from(value: base_client_gen::ConfigStatus) -> Self {
ConfigStatus {
error: value.error.map(Into::into),
last_transition_time: value.last_transition_time,
version: value.version,
}
}
}
impl From<ConfigError> for base_client_gen::ConfigError {
fn from(value: ConfigError) -> Self {
base_client_gen::ConfigError {
code: value.code,
message: value.message,
details: value.details.option_vec_into(),
}
}
}
impl From<base_client_gen::ConfigError> for ConfigError {
fn from(value: base_client_gen::ConfigError) -> Self {
ConfigError {
code: value.code,
message: value.message,
details: value.details.option_vec_into(),
}
}
}
impl From<Details> for base_client_gen::DetailsSchemaElementSchema {
fn from(value: Details) -> Self {
base_client_gen::DetailsSchemaElementSchema {
code: value.code,
correlation_id: value.correlation_id,
info: value.info,
message: value.message,
}
}
}
impl From<base_client_gen::DetailsSchemaElementSchema> for Details {
fn from(value: base_client_gen::DetailsSchemaElementSchema) -> Self {
Details {
code: value.code,
correlation_id: value.correlation_id,
info: value.info,
message: value.message,
}
}
}