mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
fix: Only emit TransportsModified if transports are really modified
Otherwise it's not possible to write tests reliably because sync messages may be executed multiple times if they arrive from different transports. This should fix flaky `test_transport_synchronization`. Also always emit `TransportsModified` if the primary transport is changed by a sync message, even if it doesn't contain `SyncData::Transports`. Also don't decrease `add_timestamp` in `save_transport()` if nothing else changes, this doesn't make sense.
This commit is contained in:
@@ -417,12 +417,12 @@ pub enum EventType {
|
||||
chat_id: ChatId,
|
||||
},
|
||||
|
||||
/// One or more transports has changed.
|
||||
/// One or more transports has changed or another transport is primary now.
|
||||
///
|
||||
/// UI should update the list.
|
||||
///
|
||||
/// This event is emitted when transport
|
||||
/// synchronization messages arrives,
|
||||
/// This event is emitted when a transport
|
||||
/// synchronization message modifies transports,
|
||||
/// but not when the UI modifies the transport list by itself.
|
||||
TransportsModified,
|
||||
|
||||
|
||||
@@ -832,7 +832,9 @@ pub(crate) async fn receive_imf_inner(
|
||||
|
||||
let transport_changed = if transport_exists {
|
||||
transaction.execute(
|
||||
"UPDATE config SET value=? WHERE keyname='configured_addr'",
|
||||
"
|
||||
UPDATE config SET value=? WHERE keyname='configured_addr' AND value!=?1
|
||||
",
|
||||
(from_addr,),
|
||||
)? > 0
|
||||
} else {
|
||||
@@ -848,6 +850,7 @@ pub(crate) async fn receive_imf_inner(
|
||||
if transport_changed {
|
||||
info!(context, "Primary transport changed to {from_addr:?}.");
|
||||
context.sql.uncache_raw_config("configured_addr").await;
|
||||
context.emit_event(EventType::TransportsModified);
|
||||
}
|
||||
} else {
|
||||
warn!(context, "Sync items are not encrypted.");
|
||||
|
||||
@@ -621,16 +621,17 @@ impl From<ConfiguredLoginParam> for ConfiguredLoginParamJson {
|
||||
}
|
||||
|
||||
/// Saves transport to the database.
|
||||
/// Returns whether transports are modified.
|
||||
pub(crate) async fn save_transport(
|
||||
context: &Context,
|
||||
entered_param: &EnteredLoginParam,
|
||||
configured: &ConfiguredLoginParamJson,
|
||||
add_timestamp: i64,
|
||||
) -> Result<()> {
|
||||
) -> Result<bool> {
|
||||
let addr = addr_normalize(&configured.addr);
|
||||
let configured_addr = context.get_config(Config::ConfiguredAddr).await?;
|
||||
|
||||
context
|
||||
let mut modified = context
|
||||
.sql
|
||||
.execute(
|
||||
"INSERT INTO transports (addr, entered_param, configured_param, add_timestamp)
|
||||
@@ -638,7 +639,10 @@ pub(crate) async fn save_transport(
|
||||
ON CONFLICT (addr)
|
||||
DO UPDATE SET entered_param=excluded.entered_param,
|
||||
configured_param=excluded.configured_param,
|
||||
add_timestamp=excluded.add_timestamp",
|
||||
add_timestamp=excluded.add_timestamp
|
||||
WHERE entered_param != excluded.entered_param
|
||||
OR configured_param != excluded.configured_param
|
||||
OR add_timestamp < excluded.add_timestamp",
|
||||
(
|
||||
&addr,
|
||||
serde_json::to_string(entered_param)?,
|
||||
@@ -646,7 +650,8 @@ pub(crate) async fn save_transport(
|
||||
add_timestamp,
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
.await?
|
||||
> 0;
|
||||
|
||||
if configured_addr.is_none() {
|
||||
// If there is no transport yet, set the new transport as the primary one
|
||||
@@ -654,8 +659,9 @@ pub(crate) async fn save_transport(
|
||||
.sql
|
||||
.set_raw_config(Config::ConfiguredAddr.as_ref(), Some(&addr))
|
||||
.await?;
|
||||
modified = true;
|
||||
}
|
||||
Ok(())
|
||||
Ok(modified)
|
||||
}
|
||||
|
||||
/// Sends a sync message to synchronize transports across devices.
|
||||
@@ -721,24 +727,25 @@ pub(crate) async fn sync_transports(
|
||||
transports: &[TransportData],
|
||||
removed_transports: &[RemovedTransportData],
|
||||
) -> Result<()> {
|
||||
let mut modified = false;
|
||||
for TransportData {
|
||||
configured,
|
||||
entered,
|
||||
timestamp,
|
||||
} in transports
|
||||
{
|
||||
save_transport(context, entered, configured, *timestamp).await?;
|
||||
modified |= save_transport(context, entered, configured, *timestamp).await?;
|
||||
}
|
||||
|
||||
context
|
||||
.sql
|
||||
.transaction(|transaction| {
|
||||
for RemovedTransportData { addr, timestamp } in removed_transports {
|
||||
transaction.execute(
|
||||
modified |= transaction.execute(
|
||||
"DELETE FROM transports
|
||||
WHERE addr=? AND add_timestamp<=?",
|
||||
(addr, timestamp),
|
||||
)?;
|
||||
)? > 0;
|
||||
transaction.execute(
|
||||
"INSERT INTO removed_transports (addr, remove_timestamp)
|
||||
VALUES (?, ?)
|
||||
@@ -752,7 +759,9 @@ pub(crate) async fn sync_transports(
|
||||
})
|
||||
.await?;
|
||||
|
||||
context.emit_event(EventType::TransportsModified);
|
||||
if modified {
|
||||
context.emit_event(EventType::TransportsModified);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user