Joffrey JAFFEUX 90efdd7f9d
PERF: cook message in background (#24227)
This commit starts from a simple observation: cooking messages on the hot path can be slow. Especially with a lot of mentions.

To move cooking from the hot path, this commit has made the following changes:

- updating cooked, inserting mentions and notifying user of new mentions has been moved inside the `process_message` job. It happens right after the `Chat::MessageProcessor` run, which is where the cooking happens.
- the similar existing code in `rebake!` has also been moved to rely on the `process_message`job only
- refactored `create_mentions` and `update_mentions` into one single `upsert_mentions` which can be called invariably
- allows services to decide if their job is ran inline or later. It avoids to need to know you have to use `Jobs.run_immediately!` in this case, in tests it will be inline per default
- made various frontend changes to make the chat-channel component lifecycle clearer. we had to handle `did-update @channel` which was super awkward and creating bugs with listeners which the changes of the PR made clear in failing specs
- adds a new `-processed` (and `-not-processed`) class on the chat message, this is made to have a good lifecyle hook in system specs
2023-11-06 15:45:30 +01:00

86 lines
2.4 KiB
Handlebars

<div
class={{concat-class
"chat-channel"
(if this.messagesLoader.loading "loading")
(if this.pane.sending "chat-channel--sending")
(unless this.messagesLoader.fetchedOnce "chat-channel--not-loaded-once")
}}
{{did-insert this.setUploadDropZone}}
{{did-insert this.setupListeners}}
{{will-destroy this.teardownListeners}}
{{did-insert this.didUpdateChannel}}
{{did-insert this.addAutoFocusEventListener}}
{{will-destroy this.removeAutoFocusEventListener}}
data-id={{@channel.id}}
>
<ChatFullPageHeader
@channel={{@channel}}
@onCloseFullScreen={{this.onCloseFullScreen}}
@displayed={{this.includeHeader}}
/>
<Chat::Notices @channel={{@channel}} />
<ChatMentionWarnings />
<div
class="chat-messages-scroll chat-messages-container popper-viewport"
{{did-insert this.setScrollable}}
{{chat/scrollable-list
(hash onScroll=this.onScroll onScrollEnd=this.onScrollEnd reverse=true)
}}
>
<div
class="chat-messages-container"
{{chat/on-resize this.didResizePane (hash delay=100 immediate=true)}}
>
{{#each this.messagesManager.messages key="id" as |message|}}
<ChatMessage
@message={{message}}
@disableMouseEvents={{this.isScrolling}}
@resendStagedMessage={{this.resendStagedMessage}}
@fetchMessagesByDate={{this.fetchMessagesByDate}}
@context="channel"
/>
{{else}}
{{#unless this.messagesLoader.fetchedOnce}}
<ChatSkeleton />
{{/unless}}
{{/each}}
</div>
{{! at bottom even if shown at top due to column-reverse }}
{{#if this.messagesLoader.loadedPast}}
<div class="all-loaded-message">
{{i18n "chat.all_loaded"}}
</div>
{{/if}}
</div>
<Chat::ScrollToBottomArrow
@onScrollToBottom={{this.scrollToLatestMessage}}
@isVisible={{this.needsArrow}}
/>
{{#if this.pane.selectingMessages}}
<Chat::SelectionManager
@enableMove={{and
(not @channel.isDirectMessageChannel)
@channel.canModerate
}}
@pane={{this.pane}}
/>
{{else}}
{{#if (and (not @channel.isFollowing) @channel.isCategoryChannel)}}
<ChatChannelPreviewCard @channel={{@channel}} />
{{else}}
<Chat::Composer::Channel
@channel={{@channel}}
@uploadDropZone={{this.uploadDropZone}}
@onSendMessage={{this.onSendMessage}}
/>
{{/if}}
{{/if}}
<ChatUploadDropZone @model={{@channel}} />
</div>