use anyhow::Result;
use aries_askar::entry::{Entry, TagFilter};
use aries_askar::storage::backend::OrderBy;
use aries_askar::Store;
use crate::progress::{db_wait, Heartbeat};
#[allow(clippy::too_many_arguments)]
pub async fn for_each<F>(
store: &Store,
profile: Option<String>,
category: &str,
tag_filter: Option<TagFilter>,
label: &str,
category_label: &str,
heartbeat_every: u64,
group_size: usize,
dry_run: bool,
mut f: F,
) -> Result<u64>
where
F: FnMut(&Entry) -> Result<bool>,
{
let wait_label = format!("{label} — {category_label}");
let mut hb = Heartbeat::new(label, category_label, heartbeat_every, dry_run);
let mut scan = db_wait(
&wait_label,
store.scan(
profile,
Some(category.to_string()),
tag_filter,
None,
None,
Some(OrderBy::Id),
false,
),
)
.await?;
let group_size = group_size.max(1) as u64;
let mut scanned: u64 = 0;
let mut affected: u64 = 0;
loop {
let Some(page) = db_wait(&wait_label, scan.fetch_next()).await? else {
break;
};
for entry in &page {
if f(entry)? {
affected += 1;
}
scanned += 1;
if scanned % group_size == 0 {
hb.batch(scanned, affected);
}
}
}
Ok(scanned)
}
#[allow(clippy::too_many_arguments)]
pub async fn collect_ids(
store: &Store,
profile: Option<String>,
category: &str,
label: &str,
category_label: &str,
heartbeat_every: u64,
group_size: usize,
sink: &mut std::collections::HashSet<String>,
) -> Result<u64> {
for_each(
store,
profile,
category,
None,
label,
category_label,
heartbeat_every,
group_size,
true,
|entry| {
sink.insert(entry.name.clone());
Ok(true)
},
)
.await
}
pub fn tag_value<'e>(entry: &'e Entry, name: &str) -> Option<&'e str> {
entry
.tags
.iter()
.find(|t| t.name() == name)
.map(|t| t.value())
}