refactor: optimize sync and list operation by join
This commit is contained in:
parent
ae423c1a53
commit
96749af57f
3 changed files with 70 additions and 10 deletions
|
|
@ -443,16 +443,33 @@ pub async fn hydrate_ciphers_attachments(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut map = load_attachment_map_json(db, body, path).await?;
|
let map = load_attachment_map_json(db, body, path).await?;
|
||||||
|
apply_attachment_map(ciphers, map);
|
||||||
|
|
||||||
for cipher in ciphers.iter_mut() {
|
Ok(())
|
||||||
if let Some(list) = map.remove(&cipher.id) {
|
}
|
||||||
if !list.is_empty() {
|
|
||||||
cipher.attachments = Some(list);
|
/// Batch hydrate attachments for all ciphers belonging to a user without serializing ids.
|
||||||
}
|
pub async fn hydrate_ciphers_attachments_for_user(
|
||||||
}
|
db: &D1Database,
|
||||||
|
env: &Env,
|
||||||
|
ciphers: &mut [Cipher],
|
||||||
|
user_id: &str,
|
||||||
|
) -> Result<(), AppError> {
|
||||||
|
if ciphers.is_empty() {
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !attachments_enabled(env) {
|
||||||
|
for cipher in ciphers.iter_mut() {
|
||||||
|
cipher.attachments = None;
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let map = load_attachment_map_for_user(db, user_id).await?;
|
||||||
|
apply_attachment_map(ciphers, map);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -627,6 +644,32 @@ async fn load_attachment_map_json(
|
||||||
.results()
|
.results()
|
||||||
.map_err(|_| AppError::Database)?;
|
.map_err(|_| AppError::Database)?;
|
||||||
|
|
||||||
|
Ok(build_attachment_map(attachments))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn load_attachment_map_for_user(
|
||||||
|
db: &D1Database,
|
||||||
|
user_id: &str,
|
||||||
|
) -> Result<HashMap<String, Vec<AttachmentResponse>>, AppError> {
|
||||||
|
let attachments: Vec<AttachmentDB> = db
|
||||||
|
.prepare(
|
||||||
|
"SELECT a.* FROM attachments a \
|
||||||
|
JOIN ciphers c ON a.cipher_id = c.id \
|
||||||
|
WHERE c.user_id = ?1",
|
||||||
|
)
|
||||||
|
.bind(&[user_id.into()])?
|
||||||
|
.all()
|
||||||
|
.await
|
||||||
|
.map_err(|_| AppError::Database)?
|
||||||
|
.results()
|
||||||
|
.map_err(|_| AppError::Database)?;
|
||||||
|
|
||||||
|
Ok(build_attachment_map(attachments))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_attachment_map(
|
||||||
|
attachments: Vec<AttachmentDB>,
|
||||||
|
) -> HashMap<String, Vec<AttachmentResponse>> {
|
||||||
let mut map: HashMap<String, Vec<AttachmentResponse>> = HashMap::new();
|
let mut map: HashMap<String, Vec<AttachmentResponse>> = HashMap::new();
|
||||||
|
|
||||||
for attachment in attachments {
|
for attachment in attachments {
|
||||||
|
|
@ -636,7 +679,17 @@ async fn load_attachment_map_json(
|
||||||
.push(attachment.to_response(None));
|
.push(attachment.to_response(None));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(map)
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_attachment_map(ciphers: &mut [Cipher], mut map: HashMap<String, Vec<AttachmentResponse>>) {
|
||||||
|
for cipher in ciphers.iter_mut() {
|
||||||
|
if let Some(list) = map.remove(&cipher.id) {
|
||||||
|
if !list.is_empty() {
|
||||||
|
cipher.attachments = Some(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn upload_to_r2(
|
async fn upload_to_r2(
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,13 @@ pub async fn list_ciphers(
|
||||||
|
|
||||||
let mut ciphers: Vec<Cipher> = ciphers_db.into_iter().map(|c| c.into()).collect();
|
let mut ciphers: Vec<Cipher> = ciphers_db.into_iter().map(|c| c.into()).collect();
|
||||||
|
|
||||||
attachments::hydrate_ciphers_attachments(&db, env.as_ref(), &mut ciphers, None, None).await?;
|
attachments::hydrate_ciphers_attachments_for_user(
|
||||||
|
&db,
|
||||||
|
env.as_ref(),
|
||||||
|
&mut ciphers,
|
||||||
|
&claims.sub,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(Json(CipherListResponse {
|
Ok(Json(CipherListResponse {
|
||||||
data: ciphers,
|
data: ciphers,
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,8 @@ pub async fn get_sync_data(
|
||||||
.collect::<Vec<Cipher>>();
|
.collect::<Vec<Cipher>>();
|
||||||
|
|
||||||
let mut ciphers = ciphers;
|
let mut ciphers = ciphers;
|
||||||
attachments::hydrate_ciphers_attachments(&db, env.as_ref(), &mut ciphers, None, None).await?;
|
attachments::hydrate_ciphers_attachments_for_user(&db, env.as_ref(), &mut ciphers, &user_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let profile = Profile::from_user(user)?;
|
let profile = Profile::from_user(user)?;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue