Skip to content

Commit

Permalink
feat: Add caching to Secrets struct to improve performance (#813)
Browse files Browse the repository at this point in the history
#### Migration notes

- [ ] The change comes with new or modified tests
- [ ] Hard-to-understand functions have explanatory comments
- [ ] End-user documentation is updated to reflect the change
  • Loading branch information
j03-dev authored Aug 23, 2024
1 parent 58d220f commit 2db4e13
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 55 deletions.
8 changes: 3 additions & 5 deletions meta-cli/src/cli/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ impl Deploy {
let options = deploy.options.clone();

let node_config = config.node(&deploy.node, &deploy.target);
let secrets = Secrets::load_from_node_config(&node_config);
let secrets = Secrets::load_from_node_config(&node_config, dir.to_path_buf());
let node = node_config
.build(&dir)
.await
Expand Down Expand Up @@ -209,8 +209,7 @@ mod default_mode {

let action_generator = DeployActionGenerator::new(
deploy.node.into(),
// TODO no hydrate here
secrets.hydrate(deploy.base_dir.clone()).await?.into(),
secrets.into(),
deploy.config.dir().unwrap_or_log().into(),
deploy.base_dir.clone(),
deploy
Expand Down Expand Up @@ -293,8 +292,7 @@ mod watch_mode {

let action_generator = DeployActionGenerator::new(
deploy.node.into(),
// TODO no hydrate here
secrets.hydrate(deploy.base_dir.clone()).await?.into(),
secrets.into(),
deploy.config.dir().unwrap_or_log().into(),
deploy.base_dir.clone(),
deploy
Expand Down
11 changes: 5 additions & 6 deletions meta-cli/src/deploy/actors/task/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl TaskAction for DeployAction {
Ok(serde_json::to_value(deploy_target)?)
}

RpcCall::GetDeployData { typegraph } => Ok(self.get_deploy_data(typegraph)),
RpcCall::GetDeployData { typegraph } => Ok(self.get_deploy_data(typegraph).await?),
}
}
}
Expand All @@ -321,7 +321,7 @@ impl MigrationAction {
}

impl DeployActionInner {
fn get_deploy_data(&self, typegraph: &str) -> serde_json::Value {
async fn get_deploy_data(&self, typegraph: &str) -> Result<serde_json::Value> {
let default_action = &self.shared_config.default_migration_action;
let actions = self
.task_options
Expand All @@ -339,11 +339,10 @@ impl DeployActionInner {
})
.collect::<HashMap<_, _>>();

// TODO hydrate secrets here + cache
serde_json::json!({
"secrets": self.secrets.get(typegraph),
Ok(serde_json::json!({
"secrets": self.secrets.get(typegraph).await?,
"defaultMigrationAction": default_action,
"migrationActions": actions
})
}))
}
}
79 changes: 35 additions & 44 deletions meta-cli/src/secrets.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
// Copyright Metatype OÜ, licensed under the Mozilla Public License Version 2.0.
// SPDX-License-Identifier: MPL-2.0

use crate::interlude::*;
use tokio::sync::Mutex;

use crate::config::NodeConfig;
use crate::interlude::*;

#[derive(Debug, Clone)]
pub struct Raw;
#[derive(Debug, Clone, Default)]
pub struct Hydrated;
lazy_static::lazy_static! {
static ref CACHED_SECRETS: Mutex<HashMap<String, HashMap<String, String>>> = Mutex::new(HashMap::new());
}

// tg_name -> key -> value
#[derive(Debug, Clone, Default)]
pub struct Secrets<T = Hydrated> {
pub struct Secrets {
by_typegraph: HashMap<String, HashMap<String, String>>,
overrides: HashMap<String, String>,
_type_state: std::marker::PhantomData<T>,
path: PathBuf,
}

pub type RawSecrets = Secrets<Raw>;
pub type RawSecrets = Secrets;

struct SecretOverride<'a> {
tg_name: Option<&'a str>,
Expand Down Expand Up @@ -54,12 +54,12 @@ impl<'a> SecretOverride<'a> {
}
}

impl Secrets<Raw> {
pub fn load_from_node_config(node_config: &NodeConfig) -> Secrets<Raw> {
impl Secrets {
pub fn load_from_node_config(node_config: &NodeConfig, path: PathBuf) -> Secrets {
Secrets {
by_typegraph: node_config.secrets.clone(),
overrides: HashMap::new(),
_type_state: std::marker::PhantomData,
path,
}
}

Expand Down Expand Up @@ -87,43 +87,34 @@ impl Secrets<Raw> {
Ok(())
}

#[tracing::instrument(err)]
pub async fn hydrate(self, dir: Arc<Path>) -> Result<Secrets<Hydrated>> {
let by_typegraph: HashMap<String, _> =
futures::future::join_all(self.by_typegraph.into_iter().map(|(tg_name, secrets)| {
let dir = dir.clone();
async move {
let secrets = lade_sdk::hydrate(secrets, dir.clone().to_path_buf())
.await
.map_err(anyhow_to_eyre!())
.with_context(|| format!("error hydrating secrets for {tg_name}"))?;
Ok((tg_name, secrets))
}
}))
.await
.into_iter()
.collect::<Result<_>>()?;

let overrides = lade_sdk::hydrate(self.overrides, dir.to_path_buf())
.await
.map_err(|err| ferr!("error hydrating secrets overrides: {err}"))?;

Ok(Secrets {
by_typegraph,
overrides,
_type_state: std::marker::PhantomData,
})
}
}
pub async fn get(&self, tg_name: &str) -> Result<HashMap<String, String>> {
let mut cache = CACHED_SECRETS.lock().await;
if let Some(cached_result) = cache.get(tg_name) {
return Ok(cached_result.clone());
}

impl Secrets<Hydrated> {
pub fn get(&self, tg_name: &str) -> HashMap<String, String> {
let mut secrets = self.by_typegraph.get(tg_name).cloned().unwrap_or_default();

for (key, value) in &self.overrides {
secrets.insert(key.clone(), value.clone());
lade_sdk::hydrate(secrets.clone(), self.path.clone())
.await
.map_err(anyhow_to_eyre!())
.with_context(|| format!("error hydrating secrets for {tg_name}"))?;

if !cache.contains_key("overrides") {
let hydrated_overrides = lade_sdk::hydrate(self.overrides.clone(), self.path.clone())
.await
.map_err(|err| ferr!("error hydrating secrets overrides: {err}"))?;
cache.insert("overrides".to_string(), hydrated_overrides);
}

secrets
if let Some(overrides) = cache.get("overrides") {
for (key, value) in overrides {
secrets.insert(key.clone(), value.clone());
}
}

cache.insert(tg_name.to_string(), secrets.clone());

Ok(secrets)
}
}

0 comments on commit 2db4e13

Please sign in to comment.