Skip to content

[FIX] mail_ux: read only the last message in channel_fetched - #503

Closed
fw-bot-adhoc wants to merge 2 commits into
ingadhoc:19.0from
adhoc-dev:19.0-18.0-t-79479-az-11241-fw
Closed

fw-bot-adhoc wants to merge 2 commits into
ingadhoc:19.0from
adhoc-dev:19.0-18.0-t-79479-az-11241-fw

Conversation

@fw-bot-adhoc

Copy link
Copy Markdown
Contributor

Cada mensaje nuevo en un chat de Discuss hace que Odoo 18 lea todos los mensajes de ese chat, una vez por cada pestaña abierta de cada participante, solo para saber cuál es el último. En chats de muchos años (decenas de miles de mensajes) eso pasa a ser lo que más SQL consume en la base y la frena. Este PR hace que lea solo el último mensaje.

Tarea: https://www.adhoc.inc/odoo/project.task/79479

Qué pasa en upstream

  • El cliente web llama a discuss.channel.channel_fetched cada vez que llega un mensaje nuevo por el bus a un canal que no es de tipo channel (mail/static/src/discuss/core/common/discuss_core_common_service.js). Lo llama cada pestaña de cada miembro.
  • channel_fetched hace channel.message_ids.ids[0]: resuelve el one2many entero, con el chequeo de acceso de mail.message._search, para quedarse con el primer id.
  • El filtro channel_type in {chat, whatsapp} está después de esa carga, así que en los grupos también lee todo el canal y después lo descarta.
  • En master Odoo sacó channel_fetched y el campo fetched_message_id. En 18.0 y 19.0 sigue igual.

Qué cambia

Override de channel_fetched en mail_ux:

  • chequea channel_type antes de buscar nada;
  • busca el último mensaje con el mismo dominio que message_ids (model, res_id, message_type != user_notification), order="id desc" y limit=1, como el usuario actual. Es lo mismo que hace master con _search(..., order="id desc", limit=1).

El resto del método (búsqueda del miembro, UPDATE ... SKIP LOCKED y la notificación por bus) queda igual que upstream.

Medición

En la base más afectada de la flota, channel_fetched era el 54,6% del tiempo SQL de un día hábil: 8.151 llamadas a 602 ms, y la consulta devolvía en promedio 15.256 filas por llamada. En la flota productiva de 18 y 19, 102 bases llamaron a channel_fetched ese día y en 77 cuesta menos de 50 ms por llamada.

Pruebas

  • test_chat_fetched_reads_only_last_message: en un chat con varios mensajes y un user_notification al final, fetched_message_id queda en el último mensaje visible y mail.message._search se llama una sola vez, con limit=1. Con el código de upstream falla, porque message_ids busca sin límite.
  • test_group_fetched_is_skipped: en un grupo no se busca ningún mensaje.
  • Prueba manual pendiente en una base de test con chats grandes: el tiempo de channel_fetched en el log de acceso tiene que bajar a pocos ms, sin depender del tamaño del chat.

Después del merge sale el forward-port a 19.0, donde el método es igual.

Forward-Port-Of: #501

@roboadhoc

Copy link
Copy Markdown
Contributor

Pull request status dashboard

@fw-bot-adhoc

Copy link
Copy Markdown
Contributor Author

@az-adhoc @maq-adhoc cherrypicking of pull request #501 failed.

stdout:

Auto-merging mail_ux/models/__init__.py
Auto-merging mail_ux/tests/__init__.py
CONFLICT (add/add): Merge conflict in mail_ux/tests/__init__.py

Either perform the forward-port manually (and push to this branch, proceeding as usual) or close this PR (maybe?).

:shipit: you can use git-fw to re-do the forward-port for you locally.

⚠️ after resolving this conflict, you will need to merge it via @roboadhoc.

More info at https://github.com/odoo/odoo/wiki/Mergebot#forward-port

Upstream channel_fetched resolves the whole message_ids of the channel to
keep its first id. The browser calls it on every new message in a chat,
from every open tab of every member, so on chats with tens of thousands
of messages it becomes the main SQL cost of the database.

Search the last message with the message_ids domain and limit=1, as the
current user, and check the channel type before reading anything.
In 19.0 the test creates the chat and the group with _get_or_create_chat
and _create_group, which replace channel_get and create_group.

X-original-commit: c42ab02
@az-adhoc
az-adhoc force-pushed the 19.0-18.0-t-79479-az-11241-fw branch from 6a59c9f to 84dee34 Compare November 12, 2026 12:33
@az-adhoc

Copy link
Copy Markdown
Contributor

@roboadhoc r+ nobump

@roboadhoc

Copy link
Copy Markdown
Contributor

@az-adhoc @maq-adhoc 'ci/runbot-oba' failed on this reviewed PR.

MailCommon sets Belgium as the country of the admin user. On a database
where the admin partner belongs to a company with an Argentinian VAT, the
address sync to the company fails the VAT check and setUpClass breaks.
The test only needs two internal users, so it creates them.
@az-adhoc

Copy link
Copy Markdown
Contributor

@roboadhoc r+ squash

@roboadhoc

Copy link
Copy Markdown
Contributor

Merge method set to squash.

roboadhoc pushed a commit that referenced this pull request Nov 12, 2026
Cada mensaje nuevo en un chat de Discuss hace que Odoo 18 lea todos los mensajes de ese chat, una vez por cada pestaña abierta de cada participante, solo para saber cuál es el último. En chats de muchos años (decenas de miles de mensajes) eso pasa a ser lo que más SQL consume en la base y la frena. Este PR hace que lea solo el último mensaje.

Tarea: https://www.adhoc.inc/odoo/project.task/79479

## Qué pasa en upstream

- El cliente web llama a `discuss.channel.channel_fetched` cada vez que llega un mensaje nuevo por el bus a un canal que no es de tipo `channel` (`mail/static/src/discuss/core/common/discuss_core_common_service.js`). Lo llama cada pestaña de cada miembro.
- `channel_fetched` hace `channel.message_ids.ids[0]`: resuelve el one2many entero, con el chequeo de acceso de `mail.message._search`, para quedarse con el primer id.
- El filtro `channel_type in {chat, whatsapp}` está después de esa carga, así que en los grupos también lee todo el canal y después lo descarta.
- En `master` Odoo sacó `channel_fetched` y el campo `fetched_message_id`. En 18.0 y 19.0 sigue igual.

## Qué cambia

Override de `channel_fetched` en `mail_ux`:

- chequea `channel_type` antes de buscar nada;
- busca el último mensaje con el mismo dominio que `message_ids` (`model`, `res_id`, `message_type != user_notification`), `order="id desc"` y `limit=1`, como el usuario actual. Es lo mismo que hace `master` con `_search(..., order="id desc", limit=1)`.

El resto del método (búsqueda del miembro, `UPDATE ... SKIP LOCKED` y la notificación por bus) queda igual que upstream.

## Medición

En la base más afectada de la flota, `channel_fetched` era el 54,6% del tiempo SQL de un día hábil: 8.151 llamadas a 602 ms, y la consulta devolvía en promedio 15.256 filas por llamada. En la flota productiva de 18 y 19, 102 bases llamaron a `channel_fetched` ese día y en 77 cuesta menos de 50 ms por llamada.

## Pruebas

- `test_chat_fetched_reads_only_last_message`: en un chat con varios mensajes y un `user_notification` al final, `fetched_message_id` queda en el último mensaje visible y `mail.message._search` se llama una sola vez, con `limit=1`. Con el código de upstream falla, porque `message_ids` busca sin límite.
- `test_group_fetched_is_skipped`: en un grupo no se busca ningún mensaje.
- Prueba manual pendiente en una base de test con chats grandes: el tiempo de `channel_fetched` en el log de acceso tiene que bajar a pocos ms, sin depender del tamaño del chat.

Después del merge sale el forward-port a 19.0, donde el método es igual.

closes #503

Forward-port-of: #501
Signed-off-by: Filoquin adhoc <[email protected]>
Signed-off-by: Andrés Zacchino <[email protected]>
@roboadhoc roboadhoc closed this Nov 12, 2026
@roboadhoc
roboadhoc deleted the 19.0-18.0-t-79479-az-11241-fw branch November 12, 2026 20:07

This branch was previously deployed

1 inactive deployment
merge — ca6c1df9 Deployed Nov 12, 2026 by roboadhoc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants