· prosody mod_mam XEP-0313 gajim conversations

Prosody, MAM и битые итемы в истории

Я использую Prosody уже очень давно, и единственное, чего мне не хватало - это синхронизация истории. Несколько месяцев назад я начал искать модуль, который может мне это дать, и я нашел его - это mod_mam, который добавляет поддержку XEP-0313: Message Archiving Manager. С этим модулем Prosody хранит все в БД и предоставляет куда более простой для имплементации метод получения истории, чем XEP-0136: Message Archiving.

Оставалась всего одна проблема - отсутствие клиентов, которые бы поддерживали XEP-0313. Но недавно все изменилось - Gajim поддерживает его начиная с версии 0.16.1, и Conversations для Android поддерживает его с декабря 2014. Отлично!

Но в процессе использования я обнаружил одну очень неприятную штуку - Prosody (или сам mod_mam) создавал плохую станзу в БД, следовательно, когда клиент пытался запросить историю, Prosody высирал трейсбек и синхронизация больше не работала. Разработчики не согласны, что проблема с Prosody:

[17:49:20] Zash: pztrn: Could you apply this patch: https://prosody.im/pastebin/1ac06b94-b468-4b24-a290-749994a6b6be
[17:50:16] pztrn: http://paste.pztrn.name/1291/ here what I got in logs
[17:51:18] pztrn: lemme try to reconnect
[17:52:51] pztrn: Zash: Okay, it helps. Found a message with empty body, it causes traceback
[17:53:02] Zash: empty body?
[17:53:40] pztrn: yep
[17:53:46] Zash: That should not causet hat
[17:53:48] Zash: that*
[17:54:37] pztrn: but it cause. A assume there is a check about body length somewhere in st.deserealize(), and it returns nil. But I haven't digget into it too much :(
[17:55:59] Zash: pztrn: Could you dump that row from the db?
[17:57:39] pztrn: Zash: <message id='30492' type='chat' to='jid2' from='jid1/resource'><body></body><</message>
[17:57:54] pztrn: like that
[17:57:56] Zash: are there two << there?
[17:58:17] pztrn: nope, failed RDP copy %) sorry
[17:59:28] Zash: If you have XML in your DB then it does not call st.deserialize(), because it's a stanza already
[17:59:41] Zash: But if the XML in the DB is broken then this could happen
[18:00:15] Zash: But that means that something with our xml parsing or serializing is horribly broken
[18:00:28] pztrn: no, XML in db is fine, it was just with empty body
[18:00:44] Zash: Can't happen then!
[18:01:38] pztrn: but this happened :)
[18:16:35] Link Mauve: This is probably an issue in the client code then.
[18:16:44] Link Mauve: Which should be fixed there.
[18:17:06] Zash: Huh
[18:18:00] Zash: And it wouldn't serialize an empty <body> as <body></body>, but <body/>
[18:18:12] Zash: So there has to be some garbage in there that does something weird

Хорошо, возможно, это проблема клиента. Но я хотел пофиксить это для себя как минимум, а разбираться с исходниками мне было лень. Вот что я сделал:

Наложил этот патч, чтобы плохие итемы логировались:

diff -r aed20f9e78c8 mod_mam/mod_mam.lua
--- a/mod_mam/mod_mam.lua       Mon Mar 16 16:19:53 2015 +0100
+++ b/mod_mam/mod_mam.lua       Mon Mar 23 13:49:03 2015 +0100
@@ -145,6 +145,7 @@ module:hook("iq-set/self/"..xmlns_mam.."
                if not is_stanza(item) then
                        item = st.deserialize(item);
                end
+               if not item then module:log("error", "item %s is %s", id, tostring(item)); end
                item.attr.xmlns = "jabber:client";
                fwd_st:add_child(item);

Написал такой скрипт:

#!/bin/bash
USER="root"
PASSWORD=""
HOST="localhost"
DATABASE="prosody"

items=`grep "is nil" /var/log/prosody/prosody.log{,.1} | grep item | awk {' print $7 '}`

for item in $items; do
        mysql -h $HOST -u $USER --password=$PASSWORD -D $DATABASE -e 'DELETE FROM prosodyarchive WHERE `key` = "${item}"'
done

…и добавил его в крон:

*/10 * * * * /opt/bin/prosody_mam_kill_bad_items.sh

Пока что все хорошо, плохие итемы автоматически удаляются из БД, и синхронизация истории больше не прерывается ^_^.

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket