Skip to content

Commit c9c362d

Browse files
committed
api: get_existing_msg_ids()
This API allows to check if the message with given ID exists and distinguish between message not existing and database error. It might also be faster than checking messages one by one if multiple messages need to be checked because of using a single SQL transaction.
1 parent 6514b4c commit c9c362d

File tree

3 files changed

+66
-2
lines changed

3 files changed

+66
-2
lines changed

deltachat-jsonrpc/src/api.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ use deltachat::context::get_info;
2121
use deltachat::ephemeral::Timer;
2222
use deltachat::imex;
2323
use deltachat::location;
24-
use deltachat::message::get_msg_read_receipts;
2524
use deltachat::message::{
26-
self, delete_msgs_ex, markseen_msgs, Message, MessageState, MsgId, Viewtype,
25+
self, delete_msgs_ex, get_existing_msg_ids, get_msg_read_receipts, markseen_msgs, Message,
26+
MessageState, MsgId, Viewtype,
2727
};
2828
use deltachat::peer_channels::{
2929
leave_webxdc_realtime, send_webxdc_realtime_advertisement, send_webxdc_realtime_data,
@@ -1295,6 +1295,19 @@ impl CommandApi {
12951295
.collect())
12961296
}
12971297

1298+
/// Checks if the messages with given IDs exist.
1299+
///
1300+
/// Returns IDs of existing messages.
1301+
async fn get_existing_msg_ids(&self, account_id: u32, msg_ids: Vec<u32>) -> Result<Vec<u32>> {
1302+
let context = self.get_context(account_id).await?;
1303+
let msg_ids: Vec<MsgId> = msg_ids.into_iter().map(MsgId::new).collect();
1304+
let existing_msg_ids = get_existing_msg_ids(&context, &msg_ids).await?;
1305+
Ok(existing_msg_ids
1306+
.into_iter()
1307+
.map(|msg_id| msg_id.to_u32())
1308+
.collect())
1309+
}
1310+
12981311
async fn get_message_list_items(
12991312
&self,
13001313
account_id: u32,

src/message.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,33 @@ pub async fn markseen_msgs(context: &Context, msg_ids: Vec<MsgId>) -> Result<()>
18681868
Ok(())
18691869
}
18701870

1871+
/// Checks if the messages with given IDs exist.
1872+
///
1873+
/// Returns IDs of existing messages.
1874+
pub async fn get_existing_msg_ids(context: &Context, ids: &[MsgId]) -> Result<Vec<MsgId>> {
1875+
let query_only = true;
1876+
let res = context
1877+
.sql
1878+
.transaction_ex(query_only, |transaction| {
1879+
let mut res: Vec<MsgId> = Vec::new();
1880+
for id in ids {
1881+
if transaction.query_one(
1882+
"SELECT COUNT(*) > 0 FROM msgs WHERE id=? AND chat_id!=3",
1883+
(id,),
1884+
|row| {
1885+
let exists: bool = row.get(0)?;
1886+
Ok(exists)
1887+
},
1888+
)? {
1889+
res.push(*id);
1890+
}
1891+
}
1892+
Ok(res)
1893+
})
1894+
.await?;
1895+
Ok(res)
1896+
}
1897+
18711898
pub(crate) async fn update_msg_state(
18721899
context: &Context,
18731900
msg_id: MsgId,

src/message/message_tests.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,3 +764,27 @@ async fn test_load_unknown_viewtype() -> Result<()> {
764764
assert_eq!(bob_msg.get_viewtype(), Viewtype::Unknown);
765765
Ok(())
766766
}
767+
768+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
769+
async fn test_get_existing_msg_ids() -> Result<()> {
770+
let mut tcm = TestContextManager::new();
771+
let alice = &tcm.alice().await;
772+
let bob = &tcm.bob().await;
773+
774+
let msg1_id = tcm.send_recv(alice, bob, "Hello 1!").await.id;
775+
let msg2_id = tcm.send_recv(alice, bob, "Hello 2!").await.id;
776+
let msg3_id = tcm.send_recv(alice, bob, "Hello 3!").await.id;
777+
let msg4_id = tcm.send_recv(alice, bob, "Hello 4!").await.id;
778+
779+
assert_eq!(
780+
get_existing_msg_ids(bob, &[msg1_id, msg2_id, msg3_id, msg4_id]).await?,
781+
vec![msg1_id, msg2_id, msg3_id, msg4_id]
782+
);
783+
delete_msgs(bob, &[msg1_id, msg3_id]).await?;
784+
assert_eq!(
785+
get_existing_msg_ids(bob, &[msg1_id, msg2_id, msg3_id, msg4_id]).await?,
786+
vec![msg2_id, msg4_id]
787+
);
788+
789+
Ok(())
790+
}

0 commit comments

Comments
 (0)