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

View File

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