mirror of
https://github.com/chatmail/core.git
synced 2026-05-02 21:06:31 +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,
|
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.
|
/// UI should update the list.
|
||||||
///
|
///
|
||||||
/// This event is emitted when transport
|
/// This event is emitted when a transport
|
||||||
/// synchronization messages arrives,
|
/// synchronization message modifies transports,
|
||||||
/// but not when the UI modifies the transport list by itself.
|
/// but not when the UI modifies the transport list by itself.
|
||||||
TransportsModified,
|
TransportsModified,
|
||||||
|
|
||||||
|
|||||||
@@ -832,7 +832,9 @@ pub(crate) async fn receive_imf_inner(
|
|||||||
|
|
||||||
let transport_changed = if transport_exists {
|
let transport_changed = if transport_exists {
|
||||||
transaction.execute(
|
transaction.execute(
|
||||||
"UPDATE config SET value=? WHERE keyname='configured_addr'",
|
"
|
||||||
|
UPDATE config SET value=? WHERE keyname='configured_addr' AND value!=?1
|
||||||
|
",
|
||||||
(from_addr,),
|
(from_addr,),
|
||||||
)? > 0
|
)? > 0
|
||||||
} else {
|
} else {
|
||||||
@@ -848,6 +850,7 @@ pub(crate) async fn receive_imf_inner(
|
|||||||
if transport_changed {
|
if transport_changed {
|
||||||
info!(context, "Primary transport changed to {from_addr:?}.");
|
info!(context, "Primary transport changed to {from_addr:?}.");
|
||||||
context.sql.uncache_raw_config("configured_addr").await;
|
context.sql.uncache_raw_config("configured_addr").await;
|
||||||
|
context.emit_event(EventType::TransportsModified);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!(context, "Sync items are not encrypted.");
|
warn!(context, "Sync items are not encrypted.");
|
||||||
|
|||||||
@@ -621,16 +621,17 @@ impl From<ConfiguredLoginParam> for ConfiguredLoginParamJson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Saves transport to the database.
|
/// Saves transport to the database.
|
||||||
|
/// Returns whether transports are modified.
|
||||||
pub(crate) async fn save_transport(
|
pub(crate) async fn save_transport(
|
||||||
context: &Context,
|
context: &Context,
|
||||||
entered_param: &EnteredLoginParam,
|
entered_param: &EnteredLoginParam,
|
||||||
configured: &ConfiguredLoginParamJson,
|
configured: &ConfiguredLoginParamJson,
|
||||||
add_timestamp: i64,
|
add_timestamp: i64,
|
||||||
) -> Result<()> {
|
) -> Result<bool> {
|
||||||
let addr = addr_normalize(&configured.addr);
|
let addr = addr_normalize(&configured.addr);
|
||||||
let configured_addr = context.get_config(Config::ConfiguredAddr).await?;
|
let configured_addr = context.get_config(Config::ConfiguredAddr).await?;
|
||||||
|
|
||||||
context
|
let mut modified = context
|
||||||
.sql
|
.sql
|
||||||
.execute(
|
.execute(
|
||||||
"INSERT INTO transports (addr, entered_param, configured_param, add_timestamp)
|
"INSERT INTO transports (addr, entered_param, configured_param, add_timestamp)
|
||||||
@@ -638,7 +639,10 @@ pub(crate) async fn save_transport(
|
|||||||
ON CONFLICT (addr)
|
ON CONFLICT (addr)
|
||||||
DO UPDATE SET entered_param=excluded.entered_param,
|
DO UPDATE SET entered_param=excluded.entered_param,
|
||||||
configured_param=excluded.configured_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,
|
&addr,
|
||||||
serde_json::to_string(entered_param)?,
|
serde_json::to_string(entered_param)?,
|
||||||
@@ -646,7 +650,8 @@ pub(crate) async fn save_transport(
|
|||||||
add_timestamp,
|
add_timestamp,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?
|
||||||
|
> 0;
|
||||||
|
|
||||||
if configured_addr.is_none() {
|
if configured_addr.is_none() {
|
||||||
// If there is no transport yet, set the new transport as the primary one
|
// 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
|
.sql
|
||||||
.set_raw_config(Config::ConfiguredAddr.as_ref(), Some(&addr))
|
.set_raw_config(Config::ConfiguredAddr.as_ref(), Some(&addr))
|
||||||
.await?;
|
.await?;
|
||||||
|
modified = true;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(modified)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a sync message to synchronize transports across devices.
|
/// Sends a sync message to synchronize transports across devices.
|
||||||
@@ -721,24 +727,25 @@ pub(crate) async fn sync_transports(
|
|||||||
transports: &[TransportData],
|
transports: &[TransportData],
|
||||||
removed_transports: &[RemovedTransportData],
|
removed_transports: &[RemovedTransportData],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let mut modified = false;
|
||||||
for TransportData {
|
for TransportData {
|
||||||
configured,
|
configured,
|
||||||
entered,
|
entered,
|
||||||
timestamp,
|
timestamp,
|
||||||
} in transports
|
} in transports
|
||||||
{
|
{
|
||||||
save_transport(context, entered, configured, *timestamp).await?;
|
modified |= save_transport(context, entered, configured, *timestamp).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
context
|
context
|
||||||
.sql
|
.sql
|
||||||
.transaction(|transaction| {
|
.transaction(|transaction| {
|
||||||
for RemovedTransportData { addr, timestamp } in removed_transports {
|
for RemovedTransportData { addr, timestamp } in removed_transports {
|
||||||
transaction.execute(
|
modified |= transaction.execute(
|
||||||
"DELETE FROM transports
|
"DELETE FROM transports
|
||||||
WHERE addr=? AND add_timestamp<=?",
|
WHERE addr=? AND add_timestamp<=?",
|
||||||
(addr, timestamp),
|
(addr, timestamp),
|
||||||
)?;
|
)? > 0;
|
||||||
transaction.execute(
|
transaction.execute(
|
||||||
"INSERT INTO removed_transports (addr, remove_timestamp)
|
"INSERT INTO removed_transports (addr, remove_timestamp)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
@@ -752,7 +759,9 @@ pub(crate) async fn sync_transports(
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
context.emit_event(EventType::TransportsModified);
|
if modified {
|
||||||
|
context.emit_event(EventType::TransportsModified);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user