Software /
code /
prosody-modules
Diff
mod_mam/mod_mam.lua @ 701:cc5805f83583
mod_mam: Implement support for Result Set Management in queries.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 08 Jun 2012 03:13:31 +0200 |
parent | 675:da33325453fb |
child | 702:d94ee0848b27 |
line wrap: on
line diff
--- a/mod_mam/mod_mam.lua Thu Jun 07 23:41:25 2012 +0200 +++ b/mod_mam/mod_mam.lua Fri Jun 08 03:13:31 2012 +0200 @@ -8,6 +8,7 @@ local xmlns_forward = "urn:xmpp:forward:0"; local st = require "util.stanza"; +local rsm = module:require "rsm"; local jid_bare = require "util.jid".bare; local jid_split = require "util.jid".split; local host = module.host; @@ -62,7 +63,6 @@ local default = prefs[false]; default = default ~= nil and default_attrs[default] or global_default_policy; local reply = st.reply(stanza):tag("prefs", { xmlns = xmlns_mam, default = default }) - --module:log("debug", "get_prefs(%q) => %s", user, require"util.serialization".serialize(prefs)); local always = st.stanza("always"); local never = st.stanza("never"); for k,v in pairs(prefs) do @@ -97,7 +97,6 @@ end end - --module:log("debug", "set_prefs(%q, %s)", user, require"util.serialization".serialize(prefs)); local ok, err = set_prefs(user, prefs); if not ok then origin.send(st.error_reply(stanza, "cancel", "internal-server-error", "Error storing preferences: "..tostring(err))); @@ -119,6 +118,7 @@ local qwith = query:get_child_text("with"); local qstart = query:get_child_text("start"); local qend = query:get_child_text("end"); + local qset = rsm.get(query); module:log("debug", "Archive query, id %s with %s from %s until %s)", tostring(qid), qwith or "anyone", qstart or "the dawn of time", qend or "now"); @@ -136,19 +136,35 @@ return true end + -- RSM stuff + local qset_matches = not (qset and qset.after); + local first, last, index; + local n = 0; + local start = qset and qset.index or 1; + module:log("debug", "Loaded %d items, about to filter", #data); - for i=1,#data do + for i=start,#data do local item = data[i]; local when, with, with_bare = item.when, item.with, item.with_bare; local ts = item.timestamp; local id = item.id; + --module:log("debug", "id is %s", id); + + -- RSM pre-send-checking + if qset then + if qset.before == id then + module:log("debug", "End of matching range found"); + qset_matches = false; + break; + end + end + --module:log("debug", "message with %s at %s", with, when or "???"); -- Apply query filter if (not qwith or ((qwith == with) or (qwith == with_bare))) and (not qstart or when >= qstart) - and (not qend or when <= qend) then - -- Optimizable? Do this when archiving? - --module:log("debug", "sending"); + and (not qend or when <= qend) + and (not qset or qset_matches) then local fwd_st = st.message{ to = origin.full_jid } :tag("result", { xmlns = xmlns_mam, queryid = qid, id = id }):up() :tag("forwarded", { xmlns = xmlns_forward }) @@ -157,13 +173,32 @@ orig_stanza.attr.xmlns = "jabber:client"; fwd_st:add_child(orig_stanza); origin.send(fwd_st); - elseif qend and when > qend then + if not first then + index = i; + first = id; + end + last = id; + n = n + 1; + elseif (qend and when > qend) then + module:log("debug", "We have passed into messages more recent than requested"); break -- We have passed into messages more recent than requested end + + -- RSM post-send-checking + if qset then + if qset.after == id then + module:log("debug", "Start of matching range found"); + qset_matches = true; + end + if qset.max and n >= qset.max then + module:log("debug", "Max number of items matched"); + break + end + end end -- That's all folks! module:log("debug", "Archive query %s completed", tostring(qid)); - origin.send(st.reply(stanza)); + origin.send(st.reply(stanza):add_child(rsm.generate{first = { index = index; first }, last = last})); return true end end); @@ -221,8 +256,6 @@ local target_jid = c2s and orig_to or orig_from; local target_bare = jid_bare(target_jid); - assert(store_host == host, "This should not happen."); - if shall_store(store_user, target_bare) then module:log("debug", "Archiving stanza: %s", stanza:top_tag()); @@ -232,8 +265,7 @@ local ok, err = dm_list_append(store_user, store_host, archive_store, { -- WARNING This format may change. id = id, - when = when, -- This might be an UNIX timestamp. Probably. - timestamp = timestamp(when), -- Textual timestamp. But I'll assume that comparing numbers is faster and less annoying in case of timezones. + when = when, with = target_jid, with_bare = target_bare, -- Optimization, to avoid loads of jid_bare() calls when filtering. stanza = st.preserialize(stanza)