Use UPSERT when saving peerstates

This way there is no need to distinguish between creating
and updating peerstate.
This commit is contained in:
link2xt
2022-11-25 22:22:29 +00:00
parent 62f92d5b28
commit c7691fbebe
8 changed files with 43 additions and 54 deletions

View File

@@ -306,7 +306,7 @@ pub(crate) async fn get_autocrypt_peerstate(
if addr_cmp(&peerstate.addr, from) { if addr_cmp(&peerstate.addr, from) {
if allow_change { if allow_change {
peerstate.apply_header(header, message_time); peerstate.apply_header(header, message_time);
peerstate.save_to_db(&context.sql, false).await?; peerstate.save_to_db(&context.sql).await?;
} else { } else {
info!( info!(
context, context,
@@ -322,7 +322,7 @@ pub(crate) async fn get_autocrypt_peerstate(
// to the database. // to the database.
} else { } else {
let p = Peerstate::from_header(header, message_time); let p = Peerstate::from_header(header, message_time);
p.save_to_db(&context.sql, true).await?; p.save_to_db(&context.sql).await?;
peerstate = Some(p); peerstate = Some(p);
} }
} else { } else {

View File

@@ -310,7 +310,7 @@ impl MimeMessage {
// && decryption_info.dkim_results.allow_keychange // && decryption_info.dkim_results.allow_keychange
{ {
peerstate.degrade_encryption(message_time); peerstate.degrade_encryption(message_time);
peerstate.save_to_db(&context.sql, false).await?; peerstate.save_to_db(&context.sql).await?;
} }
} }
(Ok(mail), HashSet::new(), false) (Ok(mail), HashSet::new(), false)
@@ -1586,11 +1586,11 @@ async fn update_gossip_peerstates(
let peerstate; let peerstate;
if let Some(mut p) = Peerstate::from_addr(context, &header.addr).await? { if let Some(mut p) = Peerstate::from_addr(context, &header.addr).await? {
p.apply_gossip(&header, message_time); p.apply_gossip(&header, message_time);
p.save_to_db(&context.sql, false).await?; p.save_to_db(&context.sql).await?;
peerstate = p; peerstate = p;
} else { } else {
let p = Peerstate::from_gossip(&header, message_time); let p = Peerstate::from_gossip(&header, message_time);
p.save_to_db(&context.sql, true).await?; p.save_to_db(&context.sql).await?;
peerstate = p; peerstate = p;
}; };
peerstate peerstate

View File

@@ -410,37 +410,34 @@ impl Peerstate {
} }
} }
pub async fn save_to_db(&self, sql: &Sql, create: bool) -> Result<()> { pub async fn save_to_db(&self, sql: &Sql) -> Result<()> {
if self.to_save || create { if self.to_save {
sql.execute( sql.execute(
if create { "INSERT INTO acpeerstates (
"INSERT INTO acpeerstates ( \ last_seen,
last_seen, \ last_seen_autocrypt,
last_seen_autocrypt, \ prefer_encrypted,
prefer_encrypted, \ public_key,
public_key, \ gossip_timestamp,
gossip_timestamp, \ gossip_key,
gossip_key, \ public_key_fingerprint,
public_key_fingerprint, \ gossip_key_fingerprint,
gossip_key_fingerprint, \ verified_key,
verified_key, \ verified_key_fingerprint,
verified_key_fingerprint, \ addr)
addr \ VALUES (?,?,?,?,?,?,?,?,?,?,?)
) VALUES(?,?,?,?,?,?,?,?,?,?,?)" ON CONFLICT (addr)
} else { DO UPDATE SET
"UPDATE acpeerstates \ last_seen = excluded.last_seen,
SET last_seen=?, \ last_seen_autocrypt = excluded.last_seen_autocrypt,
last_seen_autocrypt=?, \ prefer_encrypted = excluded.prefer_encrypted,
prefer_encrypted=?, \ public_key = excluded.public_key,
public_key=?, \ gossip_timestamp = excluded.gossip_timestamp,
gossip_timestamp=?, \ gossip_key = excluded.gossip_key,
gossip_key=?, \ public_key_fingerprint = excluded.public_key_fingerprint,
public_key_fingerprint=?, \ gossip_key_fingerprint = excluded.gossip_key_fingerprint,
gossip_key_fingerprint=?, \ verified_key = excluded.verified_key,
verified_key=?, \ verified_key_fingerprint = excluded.verified_key_fingerprint",
verified_key_fingerprint=? \
WHERE addr=?"
},
paramsv![ paramsv![
self.last_seen, self.last_seen,
self.last_seen_autocrypt, self.last_seen_autocrypt,
@@ -630,12 +627,7 @@ pub async fn maybe_do_aeap_transition(
peerstate.apply_header(header, info.message_time); peerstate.apply_header(header, info.message_time);
peerstate.to_save = true; peerstate.to_save = true;
// We don't know whether a peerstate with this address already existed, or a peerstate.save_to_db(&context.sql).await?;
// new one should be created, so just try both create=false and create=true,
// and if this fails, create=true, one will succeed (this is a very cold path,
// so performance doesn't really matter).
peerstate.save_to_db(&context.sql, true).await?;
peerstate.save_to_db(&context.sql, false).await?;
} }
} }
@@ -704,7 +696,7 @@ mod tests {
}; };
assert!( assert!(
peerstate.save_to_db(&ctx.ctx.sql, true).await.is_ok(), peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
"failed to save to db" "failed to save to db"
); );
@@ -746,11 +738,11 @@ mod tests {
}; };
assert!( assert!(
peerstate.save_to_db(&ctx.ctx.sql, true).await.is_ok(), peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
"failed to save" "failed to save"
); );
assert!( assert!(
peerstate.save_to_db(&ctx.ctx.sql, true).await.is_ok(), peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
"double-call with create failed" "double-call with create failed"
); );
} }
@@ -779,7 +771,7 @@ mod tests {
}; };
assert!( assert!(
peerstate.save_to_db(&ctx.ctx.sql, true).await.is_ok(), peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
"failed to save" "failed to save"
); );

View File

@@ -897,7 +897,7 @@ mod tests {
fingerprint_changed: false, fingerprint_changed: false,
}; };
assert!( assert!(
peerstate.save_to_db(&ctx.ctx.sql, true).await.is_ok(), peerstate.save_to_db(&ctx.ctx.sql).await.is_ok(),
"failed to save peerstate" "failed to save peerstate"
); );

View File

@@ -2129,7 +2129,7 @@ async fn check_verified_properties(
&fp, &fp,
PeerstateVerifiedStatus::BidirectVerified, PeerstateVerifiedStatus::BidirectVerified,
); );
peerstate.save_to_db(&context.sql, false).await?; peerstate.save_to_db(&context.sql).await?;
is_verified = true; is_verified = true;
} }
} }

View File

@@ -641,10 +641,7 @@ async fn mark_peer_as_verified(context: &Context, fingerprint: &Fingerprint) ->
) { ) {
peerstate.prefer_encrypt = EncryptPreference::Mutual; peerstate.prefer_encrypt = EncryptPreference::Mutual;
peerstate.to_save = true; peerstate.to_save = true;
peerstate peerstate.save_to_db(&context.sql).await.unwrap_or_default();
.save_to_db(&context.sql, false)
.await
.unwrap_or_default();
return Ok(()); return Ok(());
} }
} }
@@ -935,7 +932,7 @@ mod tests {
to_save: true, to_save: true,
fingerprint_changed: false, fingerprint_changed: false,
}; };
peerstate.save_to_db(&bob.ctx.sql, true).await?; peerstate.save_to_db(&bob.ctx.sql).await?;
// Step 1: Generate QR-code, ChatId(0) indicates setup-contact // Step 1: Generate QR-code, ChatId(0) indicates setup-contact
let qr = get_securejoin_qr(&alice.ctx, None).await?; let qr = get_securejoin_qr(&alice.ctx, None).await?;

View File

@@ -280,7 +280,7 @@ impl Sql {
for addr in &addrs { for addr in &addrs {
if let Some(ref mut peerstate) = Peerstate::from_addr(context, addr).await? { if let Some(ref mut peerstate) = Peerstate::from_addr(context, addr).await? {
peerstate.recalc_fingerprint(); peerstate.recalc_fingerprint();
peerstate.save_to_db(self, false).await?; peerstate.save_to_db(self).await?;
} }
} }
} }

View File

@@ -343,7 +343,7 @@ async fn mark_as_verified(this: &TestContext, other: &TestContext) {
peerstate.verified_key_fingerprint = peerstate.public_key_fingerprint.clone(); peerstate.verified_key_fingerprint = peerstate.public_key_fingerprint.clone();
peerstate.to_save = true; peerstate.to_save = true;
peerstate.save_to_db(&this.sql, false).await.unwrap(); peerstate.save_to_db(&this.sql).await.unwrap();
} }
async fn get_last_info_msg(t: &TestContext, chat_id: ChatId) -> Option<Message> { async fn get_last_info_msg(t: &TestContext, chat_id: ChatId) -> Option<Message> {