# HG changeset patch # User Kim Alvefur # Date 1453206856 -3600 # Node ID 279885fd972815d6cfdd94b1dd795e05e79a74c5 # Parent 7f90692bbd23607a6768d9abb019b3955fbc9dbf mod_mam: Add support for trimming old archived messages diff -r 7f90692bbd23 -r 279885fd9728 mod_mam/README.markdown --- a/mod_mam/README.markdown Tue Jan 19 13:31:11 2016 +0100 +++ b/mod_mam/README.markdown Tue Jan 19 13:34:16 2016 +0100 @@ -40,6 +40,7 @@ ------------------------------ ----------------------- --------- max\_archive\_query\_results number `50` default\_archive\_policy boolean or `"roster"` `false` + archive\_expires\_after string `"1w"` Storage backend --------------- @@ -67,6 +68,30 @@ blocked while processing the request and will not be able to do anything else. +Archive expiry +-------------- + +Messages in the archive will expire after some time, by default one +week. This can be changed by setting `archive_expires_after`: + +``` {.lua} +archive_expires_after = "1d" -- one day + +archive_expires_after = "1w" -- one week, the default + +archive_expires_after = "2m" -- two months + +archive_expires_after = "1y" -- one year + +archive_expires_after = 60 * 60 -- one hour + +archive_expires_after = "never" -- forever +``` + +The format is an integer number of seconds or a multiple of a period +given by a suffix that can be one of `d` (day), `w` (week), `m` (month) +or `y` (year). No multiplier means seconds. + Message matching policy ----------------------- diff -r 7f90692bbd23 -r 279885fd9728 mod_mam/mod_mam.lua --- a/mod_mam/mod_mam.lua Tue Jan 19 13:31:11 2016 +0100 +++ b/mod_mam/mod_mam.lua Tue Jan 19 13:34:16 2016 +0100 @@ -49,6 +49,8 @@ return; end +local cleanup; + -- Handle prefs. module:hook("iq/self/"..xmlns_mam..":prefs", function(event) local origin, stanza = event.origin, event.stanza; @@ -90,6 +92,8 @@ local query = stanza.tags[1]; local qid = query.attr.queryid; + if cleanup then cleanup[origin.username] = true; end + -- Search query parameters local qwith, qstart, qend; local form = query:get_child("x", "jabber:x:data"); @@ -253,6 +257,7 @@ -- And stash it local ok, id = archive:append(store_user, nil, time_now(), with, stanza); if ok then + if cleanup then cleanup[store_user] = true; end module:fire_event("archive-message-added", { origin = origin, stanza = stanza, for_user = store_user, id = id }); end else @@ -264,6 +269,47 @@ return message_handler(event, true); end +local cleanup_after = module:get_option_string("archive_expires_after", "1w"); +local cleanup_interval = module:get_option_number("archive_expire_interval", 4 * 60 * 60); +if cleanup_after ~= "never" then + local day = 86400; + local multipliers = { d = day, w = day * 7, m = 31 * day, y = 365.2425 * day }; + local n, m = cleanup_after:lower():match("(%d+)%s*([dmy]?)"); + if not n then + module:log("error", "Could not parse archive_expires_after string %q", cleanup_after); + return false; + end + + cleanup_after = tonumber(n) * ( multipliers[m] or 1 ); + + if not archive.delete then + module:log("error", "archive_expires_after set but mod_%s does not support deleting", archive._provided_by); + return false; + end + + cleanup = {}; + + pcall(function () + local um = require "core.usermanager"; + for user in um.users(module.host) do + cleanup[user] = true; + end + end); + + module:add_timer(10, function() + local user = next(cleanup); + if user then + module:log("debug", "Removing old messages for user %q", user); + local ok, err = archive:delete(user, { ["end"] = os.time() - cleanup_after; }) + if not ok then + module:log("warn", "Could not expire archives for user %s: %s", user, err); + end + user[cleanup] = nil; + end + return 14400; + end); +end + -- Stanzas sent by local clients module:hook("pre-message/bare", c2s_message_handler, 2); module:hook("pre-message/full", c2s_message_handler, 2);