Skip to content

fix: make create_send_msg_jobs actually return row IDs - #8585

Open
link2xt wants to merge 2 commits into
mainfrom
link2xt/create_send_msg_jobs-row_id
Open

fix: make create_send_msg_jobs actually return row IDs#8585
link2xt wants to merge 2 commits into
mainfrom
link2xt/create_send_msg_jobs-row_id

Conversation

@link2xt

@link2xt link2xt commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

.execute() was returning the number of rows, so usually 1.
.insert() is returning the row ID.

In most cases it does not matter because the result is checked with .is_empty(), but send_msg_sync() actually uses the row IDs.

@link2xt

This comment was marked as outdated.

@link2xt
link2xt force-pushed the link2xt/create_send_msg_jobs-row_id branch from 20ae3c5 to 889578d Compare August 14, 2026 11:40
@link2xt link2xt mentioned this pull request Aug 22, 2026
@link2xt
link2xt force-pushed the link2xt/create_send_msg_jobs-row_id branch 2 times, most recently from 42ebbff to 1ca89ff Compare August 23, 2026 02:37
.execute() was returning the number of rows, so usually 1.
.insert() is returning the row ID.

In most cases it does not matter because the result is checked with .is_empty(),
but send_msg_sync() actually uses the row IDs.
@link2xt
link2xt force-pushed the link2xt/create_send_msg_jobs-row_id branch from 1ca89ff to e657a72 Compare August 25, 2026 14:08
@link2xt
link2xt marked this pull request as ready for review August 25, 2026 14:08
chat1.send_msg_sync(msg1)

lp.sec("ac2: receive message")
msg_in = ac2._evtracker.wait_next_incoming_message()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test gets stuck without the fix, likely here because the message is never sent out as it tries to send rowid 1 from smtp table.

@link2xt

link2xt commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator Author

Ended up writing a python test for dc_send_msg_sync() because it is the only API that is affected and only exists as CFFI. IIRC it is used by iOS for share extension.

sent_id = lib.dc_send_msg_sync(self.account._dc_context, self.id, msg._dc_msg)
if sent_id == 0:
raise ValueError("message could not be sent")
# modify message in place to avoid bad state for the caller

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is copy-pasted from a function above.

@hpk42 hpk42 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good enough (see review comments). Also i think it'd be good to have an offline Rust test queuing two messages and testing the row-id behaviour.

ac1.stop_io()
msg1 = Message.new_empty(ac1, "text")
msg1.set_text("message1")
chat1.send_msg_sync(msg1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd assert that msg1.is_out_delivered() to not land in receive-timeout if something goes wrong.

Comment on lines 262 to +305
def send_msg(self, msg: Message) -> Message:
"""send a message by using a ready Message object.

:param msg: a :class:`deltachat.message.Message` instance
previously returned by
e.g. :meth:`deltachat.message.Message.new_empty`.
:raises ValueError: if message can not be sent.

:returns: a :class:`deltachat.message.Message` instance as
sent out. This is the same object as was passed in, which
has been modified with the new state of the core.
"""
sent_id = lib.dc_send_msg(self.account._dc_context, self.id, msg._dc_msg)
if sent_id == 0:
raise ValueError("message could not be sent")
# modify message in place to avoid bad state for the caller
sent_msg = Message.from_db(self.account, sent_id)
if sent_msg is None:
raise ValueError("cannot load just sent message from the database")
msg._dc_msg = sent_msg._dc_msg
return msg

def send_msg_sync(self, msg: Message) -> Message:
"""Send a message synchronously.
This bypasses the IO scheduler and creates its own SMTP connection.

:param msg: a :class:`deltachat.message.Message` instance
previously returned by
e.g. :meth:`deltachat.message.Message.new_empty`.
:raises ValueError: if message can not be sent.

:returns: a :class:`deltachat.message.Message` instance as
sent out. This is the same object as was passed in, which
has been modified with the new state of the core.
"""
sent_id = lib.dc_send_msg_sync(self.account._dc_context, self.id, msg._dc_msg)
if sent_id == 0:
raise ValueError("message could not be sent")
# modify message in place to avoid bad state for the caller
sent_msg = Message.from_db(self.account, sent_id)
if sent_msg is None:
raise ValueError("cannot load just sent message from the database")
msg._dc_msg = sent_msg._dc_msg
return msg

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is almost complete duplication. except for one different lib call. Please consider avoiding it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants