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

Refactor config, init and tracing #78

Merged
merged 15 commits into from
Sep 27, 2023

Conversation

4t145
Copy link
Collaborator

@4t145 4t145 commented Sep 20, 2023

Config

Enable and disable

By now, if a component's config appear in config, the component is considered enabled. And each component in framwork config is Option value.

Using Builder

Configs now can be constructed from its builder, powered by crate typed_builder, e.g.:

let mq_module_config = MQModuleConfig {
            url: url.parse().expect("invalid url"),
};
// Default test
TardisFuns::init_conf(TardisConfig {
    cs: Default::default(),
    fw: FrameworkConfig::builder().mq(MQConfig::builder().default(mq_module_config.clone()).modules([("m1".to_string(), mq_module_config)]).build()).build(),
})
.await?;

Unify structure

The config of a component with multimodules now have structure bellow :

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, TypedBuilder)]
pub struct TardisComponentConfig<T, C: Default = ()> {
    #[serde(flatten)]
    #[builder(default, setter(into))]
    common: C,
    #[serde(flatten)]
    pub default: T,
    #[builder(default, setter(into))]
    #[serde(default = "Default::default")]
    pub modules: HashMap<String, T>,
}
  1. A common config structures defaut by ().
  2. A default module config.
  3. Several module-wise configs.

Init by config

A component module config can initialize the corresponded component. If there's no common config, the component config can initialize a HashMap<String, Arc<Component>>, where the default module is stored at entry empty string "".

Costom config can be mapped into varied rust types.

As if a csm config can be deserialized as rust type T, the config::<T> () call shouldn't panic now.

pub struct CachedJsonValue {
    json_value: serde_json::Value,
    cache: OnceLock<RwLock<HashMap<TypeId, Arc<dyn Any + 'static + Send + Sync>>>>,
}

Tracing

Now tracing has a component TardisTracing, user can initialize by default or customize tracing layers.

By default, the tracing layers includes fmt, envfilter, opentelemetry (when tracing feature enabled), tracing appender (a file logger, when tracing_appender feature enabled) and console-subscriber (when tokio-console feature enabled)

Add a dynamic configurable layer

TardisTracing::init()
.with_configurable_layer(EnvFilter::from_default_env(), |config| {
     let env_filter = EnvFilter::from_default_env();
     handle with config
     Ok(env_filter)
 })

update config

by calling tracing().update_config, we can reload all configurable layer.

TardisInst.tracing().update_config(&new_config);

Crypto and Digest

rust-crypto is removed for it's unmaintained now. Using works from RustCrypto instead.

Support for custom digest algorithm, result mapper and digest from iterator.

  1. digest output could be spcified to raw bytes or hex code.
  2. digest should accept iterators (in case of digest an structure or stream).
  3. digest can accept any algorithm implemented digest::Digest
    /// Digest the data, and map the output into hexcode by default.
    pub fn digest<A: digest::Digest>(&self, data: impl AsRef<[u8]>) -> TardisResult<String> {
        self.digest_hex::<A>(data)
    }

    /// Digest the data, and map the output into hexcode.
    pub fn digest_hex<A: digest::Digest>(&self, data: impl AsRef<[u8]>) -> TardisResult<String> {
        self.digest_as::<A, HexCodeMapper>(data)
    }

    /// Digest the data, and map the output into `Vec<u8>`.
    pub fn digest_bytes<A: digest::Digest>(&self, data: impl AsRef<[u8]>) -> TardisResult<Vec<u8>> {
        self.digest_as::<A, BytesMapper>(data)
    }

    /// Digest the data, and map the output into a specific type which determined by `M`.
    pub fn digest_as<A: digest::Digest, M: Mapper>(&self, data: impl AsRef<[u8]>) -> TardisResult<M::MappedType> {
        self.digest_iter_as::<A, M, _>(Some(data))
    }

Rename Aes to Aead

Now, aes algorithm accept raw bytes instead of str. Raw bytes is recommoned because from string to raw bytes is cheap while parse an hexcode is relatively expensive, and in most case we got key and data in raw bytes. User should use random_n_bytes() to generate random key rather than random_n_hex().

And several aead algorithms are supported, which are considered secure.

Misc

Use for <'a>Deserialize<'a> instead of DeserializeOwned

The restriction of for <'a>Deserialize<'a> is looser.

Use impl IntoIterator<Item = T> instead of Option<Vec<T>>

impl IntoIterator<Item = T> includes Vec<T>, Option<T> and many other types.

Use impl Into<String> instead of String

impl Into<String> includes String and &str

Copy link

@github-advanced-security github-advanced-security bot left a comment

Choose a reason for hiding this comment

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

devskim found more than 10 potential problems in the proposed changes. Check the Files changed tab for more details.

@gudaoxuri gudaoxuri merged commit 40af5e2 into ideal-world:main Sep 27, 2023
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.

2 participants