daml_grpc/service/
daml_config_management_service.rs

1use std::convert::TryFrom;
2use std::fmt::Debug;
3
4use chrono::{DateTime, Utc};
5use tonic::transport::Channel;
6use tracing::{instrument, trace};
7
8use crate::data::DamlResult;
9use crate::data::DamlTimeModel;
10use crate::grpc_protobuf::com::daml::ledger::api::v1::admin::config_management_service_client::ConfigManagementServiceClient;
11use crate::grpc_protobuf::com::daml::ledger::api::v1::admin::{GetTimeModelRequest, SetTimeModelRequest, TimeModel};
12use crate::service::common::make_request;
13use crate::util::{to_grpc_timestamp, Required};
14
15/// Provides methods for the ledger administrator to change the current ledger configuration.
16///
17/// The services provides methods to modify different aspects of the configuration.
18#[derive(Debug)]
19pub struct DamlConfigManagementService<'a> {
20    channel: Channel,
21    auth_token: Option<&'a str>,
22}
23
24impl<'a> DamlConfigManagementService<'a> {
25    pub fn new(channel: Channel, auth_token: Option<&'a str>) -> Self {
26        Self {
27            channel,
28            auth_token,
29        }
30    }
31
32    /// Override the JWT token to use for this service.
33    pub fn with_token(self, auth_token: &'a str) -> Self {
34        Self {
35            auth_token: Some(auth_token),
36            ..self
37        }
38    }
39
40    /// Return the currently active time model and the current configuration generation.
41    ///
42    /// The current configuration generation. The generation is a monotonically increasing integer that is incremented
43    /// on each change. Used when setting the time model.
44    #[instrument(skip(self))]
45    pub async fn get_time_model(&self) -> DamlResult<(i64, DamlTimeModel)> {
46        let payload = GetTimeModelRequest {};
47        trace!(payload = ?payload, token = ?self.auth_token);
48        let response = self.client().get_time_model(make_request(payload, self.auth_token)?).await?.into_inner();
49        trace!(?response);
50        Ok((response.configuration_generation, DamlTimeModel::try_from(response.time_model.req()?)?))
51    }
52
53    /// Set the ledger time model.
54    ///
55    /// # Errors
56    ///
57    /// In case of failure this method responds with:
58    ///
59    /// `INVALID_ARGUMENT` if arguments are invalid, or the provided configuration generation
60    ///   does not match the current active configuration generation. The caller is expected
61    ///   to retry by again fetching current time model using `GetTimeModel`, applying changes
62    ///   and resubmitting.
63    ///
64    /// `ABORTED` if the request is rejected or times out. Note that a timed out request may
65    ///   have still been committed to the ledger. Application should re-query the current
66    ///   time model before retrying.
67    ///
68    /// `UNIMPLEMENTED` if this method is not supported by the backing ledger.
69    #[instrument(skip(self))]
70    pub async fn set_time_model(
71        &self,
72        submission_id: impl Into<String> + Debug,
73        maximum_record_time: impl Into<DateTime<Utc>> + Debug,
74        configuration_generation: i64,
75        new_time_model: impl Into<DamlTimeModel> + Debug,
76    ) -> DamlResult<i64> {
77        let payload = SetTimeModelRequest {
78            submission_id: submission_id.into(),
79            maximum_record_time: Some(to_grpc_timestamp(maximum_record_time.into())?),
80            configuration_generation,
81            new_time_model: Some(TimeModel::try_from(new_time_model.into())?),
82        };
83        trace!(payload = ?payload, token = ?self.auth_token);
84        let response = self.client().set_time_model(make_request(payload, self.auth_token)?).await?.into_inner();
85        trace!(?response);
86        Ok(response.configuration_generation)
87    }
88
89    fn client(&self) -> ConfigManagementServiceClient<Channel> {
90        ConfigManagementServiceClient::new(self.channel.clone())
91    }
92}