mirror of
https://github.com/zulip/zulip.git
synced 2025-11-18 12:54:58 +00:00
thumbnail: Resolve a race condition when rendering messages.
Messages are rendered outside of a transaction, for performance
reasons, and then sent inside of one. This opens thumbnailing up to a
race where the thumbnails have not yet been written when the message
is rendered, but the message has not been sent when thumbnailing
completes, causing `rewrite_thumbnailed_images` to be a no-op and the
message being left with a spinner which never resolves.
Explicitly lock and use he ImageAttachment data inside the
message-sending transaction, to rewrite the message content with the
latest information about the existing thumbnails.
Despite the thumbnailing worker taking a lock on Message rows to
update them, this does not lead to deadlocks -- the INSERT of the
Message rows happens in a transaction, ensuring that either the
message rending blocks the thumbnailing until the Message row is
created, or that the `rewrite_thumbnailed_images` and Message INSERT
waits until thumbnailing is complete (and updated no Message rows).
(cherry picked from commit 6f20c15ae9)
This commit is contained in:
committed by
Tim Abbott
parent
d34183154f
commit
656ca17e14
@@ -118,6 +118,7 @@ class MessageRenderingResult:
|
||||
links_for_preview: set[str]
|
||||
user_ids_with_alert_words: set[int]
|
||||
potential_attachment_path_ids: list[str]
|
||||
thumbnail_spinners: set[str]
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -2625,6 +2626,7 @@ def do_convert(
|
||||
links_for_preview=set(),
|
||||
user_ids_with_alert_words=set(),
|
||||
potential_attachment_path_ids=[],
|
||||
thumbnail_spinners=set(),
|
||||
)
|
||||
|
||||
_md_engine.zulip_message = message
|
||||
@@ -2683,9 +2685,10 @@ def do_convert(
|
||||
|
||||
# Post-process the result with the rendered image previews:
|
||||
if user_upload_previews is not None:
|
||||
content_with_thumbnails = rewrite_thumbnailed_images(
|
||||
content_with_thumbnails, thumbnail_spinners = rewrite_thumbnailed_images(
|
||||
rendering_result.rendered_content, user_upload_previews
|
||||
)
|
||||
rendering_result.thumbnail_spinners = thumbnail_spinners
|
||||
if content_with_thumbnails is not None:
|
||||
rendering_result.rendered_content = content_with_thumbnails
|
||||
|
||||
|
||||
Reference in New Issue
Block a user