feat(config): refactor config_store to use Arc instead of plain references

This commit is contained in:
Federico Terzi 2021-07-31 11:54:13 +02:00
parent 96309709b2
commit 24910859ac
3 changed files with 28 additions and 26 deletions

View File

@ -19,6 +19,7 @@
use anyhow::Result;
use std::{collections::HashSet, path::Path};
use std::sync::Arc;
use thiserror::Error;
mod parse;
@ -33,7 +34,7 @@ use mockall::{automock, predicate::*};
use crate::error::NonFatalErrorSet;
#[cfg_attr(test, automock)]
pub trait Config: Send {
pub trait Config: Send + Sync {
fn id(&self) -> i32;
fn label(&self) -> &str;
fn match_paths(&self) -> &[String];
@ -106,9 +107,9 @@ pub trait Config: Send {
}
pub trait ConfigStore: Send {
fn default(&self) -> &dyn Config;
fn active<'a>(&'a self, app: &AppProperties) -> &'a dyn Config;
fn configs(&self) -> Vec<&dyn Config>;
fn default(&self) -> Arc<dyn Config>;
fn active<'a>(&'a self, app: &AppProperties) -> Arc<dyn Config>;
fn configs(&self) -> Vec<Arc<dyn Config>>;
fn get_all_match_paths(&self) -> HashSet<String>;
}

View File

@ -23,33 +23,34 @@ use super::{resolve::ResolvedConfig, Config, ConfigStore, ConfigStoreError};
use anyhow::{Context, Result};
use log::{debug, error};
use std::{collections::HashSet, path::Path};
use std::sync::Arc;
pub(crate) struct DefaultConfigStore {
default: Box<dyn Config>,
customs: Vec<Box<dyn Config>>,
default: Arc<dyn Config>,
customs: Vec<Arc<dyn Config>>,
}
impl ConfigStore for DefaultConfigStore {
fn default(&self) -> &dyn super::Config {
self.default.as_ref()
fn default(&self) -> Arc<dyn super::Config> {
Arc::clone(&self.default)
}
fn active<'a>(&'a self, app: &super::AppProperties) -> &'a dyn super::Config {
fn active<'a>(&'a self, app: &super::AppProperties) -> Arc<dyn super::Config> {
// Find a custom config that matches or fallback to the default one
for custom in self.customs.iter() {
if custom.is_match(app) {
return custom.as_ref();
return Arc::clone(&custom);
}
}
self.default.as_ref()
Arc::clone(&self.default)
}
fn configs(&self) -> Vec<&dyn Config> {
fn configs(&self) -> Vec<Arc<dyn Config>> {
let mut configs = Vec::new();
configs.push(self.default.as_ref());
configs.push(Arc::clone(&self.default));
for custom in self.customs.iter() {
configs.push(custom.as_ref());
configs.push(Arc::clone(&custom));
}
configs
@ -87,7 +88,7 @@ impl DefaultConfigStore {
debug!("loaded default config at path: {:?}", default_file);
// Then the others
let mut customs: Vec<Box<dyn Config>> = Vec::new();
let mut customs: Vec<Arc<dyn Config>> = Vec::new();
for entry in std::fs::read_dir(config_dir).map_err(ConfigStoreError::IOError)? {
let entry = entry?;
let config_file = entry.path();
@ -104,7 +105,7 @@ impl DefaultConfigStore {
{
match ResolvedConfig::load(&config_file, Some(&default)) {
Ok(config) => {
customs.push(Box::new(config));
customs.push(Arc::new(config));
debug!("loaded config at path: {:?}", config_file);
}
Err(err) => {
@ -120,14 +121,14 @@ impl DefaultConfigStore {
Ok((
Self {
default: Box::new(default),
default: Arc::new(default),
customs,
},
non_fatal_errors,
))
}
pub fn from_configs(default: Box<dyn Config>, customs: Vec<Box<dyn Config>>) -> Result<Self> {
pub fn from_configs(default: Arc<dyn Config>, customs: Vec<Arc<dyn Config>>) -> Result<Self> {
Ok(Self { default, customs })
}
}
@ -153,8 +154,8 @@ mod tests {
let custom2 = new_mock("custom2", true);
let store = DefaultConfigStore {
default: Box::new(default),
customs: vec![Box::new(custom1), Box::new(custom2)],
default: Arc::new(default),
customs: vec![Arc::new(custom1), Arc::new(custom2)],
};
assert_eq!(store.default().label(), "default");
@ -177,8 +178,8 @@ mod tests {
let custom2 = new_mock("custom2", false);
let store = DefaultConfigStore {
default: Box::new(default),
customs: vec![Box::new(custom1), Box::new(custom2)],
default: Arc::new(default),
customs: vec![Arc::new(custom1), Arc::new(custom2)],
};
assert_eq!(store.default().label(), "default");

View File

@ -20,7 +20,7 @@
use anyhow::Result;
use log::warn;
use regex::Regex;
use std::{collections::HashMap, path::Path};
use std::{collections::HashMap, path::Path, sync::Arc};
use self::config::LegacyConfig;
use crate::matches::{MatchEffect, group::loader::yaml::{parse::{YAMLMatch, YAMLVariable}, try_convert_into_match, try_convert_into_variable}};
@ -58,7 +58,7 @@ pub fn load(
let mut match_groups = HashMap::new();
match_groups.insert("default".to_string(), default_match_group);
let mut custom_configs: Vec<Box<dyn Config>> = Vec::new();
let mut custom_configs: Vec<Arc<dyn Config>> = Vec::new();
for custom in config_set.specific {
let (custom_config, mut custom_match_group) = split_config(custom);
deduplicate_ids(
@ -68,10 +68,10 @@ pub fn load(
);
match_groups.insert(custom_config.name.clone(), custom_match_group);
custom_configs.push(Box::new(custom_config));
custom_configs.push(Arc::new(custom_config));
}
let config_store = DefaultConfigStore::from_configs(Box::new(default_config), custom_configs)?;
let config_store = DefaultConfigStore::from_configs(Arc::new(default_config), custom_configs)?;
let match_store = LegacyMatchStore::new(match_groups);
Ok((Box::new(config_store), Box::new(match_store)))