pub mod execute;
pub mod generate;
pub mod plot;
use anyhow::{Context, Result};
use std::time::{SystemTime, UNIX_EPOCH};
use crate::config::Config;
use crate::{cell, output};
pub const FIXTURE_CELL_SLUG: &str = "FIXTURE";
pub const BENCH_TOKEN_PREFIX: &str = "BENCH";
pub const BENCH_META_TYPES: &[&str] = &[
"userProfile",
"assetMetadata",
"deviceTelemetry",
"accessPolicy",
"contentIndex",
];
pub const BENCH_RULE_TARGETS: &[&str] = &[
"userProfile",
"assetMetadata",
"accessPolicy",
];
pub const META_IDS_PER_TYPE: usize = 3;
pub fn generate(args: generate::GenerateArgs) -> Result<()> {
generate::generate(args)
}
pub async fn execute(
args: execute::ExecuteArgs,
config: &Config,
keep: bool,
) -> Result<()> {
let slug = resolve_cell_slug(args.cell_slug.as_deref())?;
cell::create(config, &slug, Some("Benchmark Cell"), "active").await?;
output::info(&format!("Executing benchmark plan: {}", args.plan));
let exec_args = execute::ExecuteArgs {
plan: args.plan,
endpoint: args.endpoint,
endpoints: args.endpoints,
strategy: args.strategy,
concurrency: args.concurrency,
cell_slug: Some(slug.clone()),
csv: args.csv,
plot: args.plot,
insecure_tls: args.insecure_tls,
};
execute::execute(exec_args).await?;
if !keep {
output::info(&format!("Cleaning up benchmark cell '{}'...", slug));
cell::purge(config, &slug).await?;
}
Ok(())
}
pub async fn run(
gen_args: generate::GenerateArgs,
exec_args: execute::ExecuteArgs,
config: &Config,
keep: bool,
) -> Result<()> {
let plan_path = format!("bench-plan-{}.db", std::process::id());
let gen = generate::GenerateArgs {
identities: gen_args.identities,
types: gen_args.types,
metas_per_identity: gen_args.metas_per_identity,
transfers_per_identity: gen_args.transfers_per_identity,
rules_per_identity: gen_args.rules_per_identity,
burns_per_identity: gen_args.burns_per_identity,
token_amount: gen_args.token_amount,
output: plan_path.clone(),
};
generate::generate(gen)?;
let exec = execute::ExecuteArgs {
plan: plan_path.clone(),
endpoint: exec_args.endpoint,
endpoints: exec_args.endpoints,
strategy: exec_args.strategy,
concurrency: exec_args.concurrency,
cell_slug: exec_args.cell_slug,
csv: exec_args.csv,
plot: exec_args.plot,
insecure_tls: exec_args.insecure_tls,
};
execute(exec, config, keep).await?;
let _ = std::fs::remove_file(&plan_path);
Ok(())
}
pub async fn clean(config: &Config, cell_slug: Option<&str>, all: bool) -> Result<()> {
if let Some(slug) = cell_slug {
cell::purge(config, slug).await?;
} else if all {
let slugs = cell::list_bench_slugs(config).await?;
if slugs.is_empty() {
output::info("No active benchmark cells found");
return Ok(());
}
output::info(&format!("Purging {} benchmark cell(s)...", slugs.len()));
for slug in &slugs {
cell::purge(config, slug).await?;
}
} else {
output::error("Specify --cell-slug <SLUG> or --all");
}
Ok(())
}
fn resolve_cell_slug(slug: Option<&str>) -> Result<String> {
match slug {
Some(s) if s.starts_with(cell::BENCH_PREFIX) => Ok(s.to_string()),
Some(s) => Ok(format!("{}{s}", cell::BENCH_PREFIX)),
None => {
let ts = SystemTime::now()
.duration_since(UNIX_EPOCH)
.context("System clock before UNIX epoch")?
.as_secs();
Ok(format!("BENCH_CLI_{ts}"))
}
}
}