Comparison

plugins/mod_muc_mam.lua @ 9880:78885b1bbb91 0.11

mod_muc_mam: Copy cleanup mechanism from mod_mam (fixes #672)
author Kim Alvefur <zash@zash.se>
date Fri, 22 Mar 2019 17:40:07 +0100
parent 9843:17060708d0eb
child 9882:18f025b3987d
child 10029:2c8f674b9243
comparison
equal deleted inserted replaced
9879:ddc07fb8dcd4 9880:78885b1bbb91
27 27
28 local is_stanza = st.is_stanza; 28 local is_stanza = st.is_stanza;
29 local tostring = tostring; 29 local tostring = tostring;
30 local time_now = os.time; 30 local time_now = os.time;
31 local m_min = math.min; 31 local m_min = math.min;
32 local timestamp, timestamp_parse = require "util.datetime".datetime, require "util.datetime".parse; 32 local timestamp, timestamp_parse, datestamp = import( "util.datetime", "datetime", "parse", "date");
33 local default_max_items, max_max_items = 20, module:get_option_number("max_archive_query_results", 50); 33 local default_max_items, max_max_items = 20, module:get_option_number("max_archive_query_results", 50);
34 34
35 local default_history_length = 20; 35 local default_history_length = 20;
36 local max_history_length = module:get_option_number("max_history_messages", math.huge); 36 local max_history_length = module:get_option_number("max_history_messages", math.huge);
37 37
38 local function get_historylength(room) 38 local function get_historylength(room)
39 return math.min(room._data.history_length or default_history_length, max_history_length); 39 return math.min(room._data.history_length or default_history_length, max_history_length);
40 end
41
42 function schedule_cleanup()
43 -- replaced by non-noop later if cleanup is enabled
40 end 44 end
41 45
42 local log_all_rooms = module:get_option_boolean("muc_log_all_rooms", false); 46 local log_all_rooms = module:get_option_boolean("muc_log_all_rooms", false);
43 local log_by_default = module:get_option_boolean("muc_log_by_default", true); 47 local log_by_default = module:get_option_boolean("muc_log_by_default", true);
44 48
349 353
350 -- And stash it 354 -- And stash it
351 local id = archive:append(room_node, nil, stored_stanza, time_now(), with); 355 local id = archive:append(room_node, nil, stored_stanza, time_now(), with);
352 356
353 if id then 357 if id then
358 schedule_cleanup(room_node);
354 stanza:add_direct_child(st.stanza("stanza-id", { xmlns = xmlns_st_id, by = self.jid, id = id })); 359 stanza:add_direct_child(st.stanza("stanza-id", { xmlns = xmlns_st_id, by = self.jid, id = id }));
355 end 360 end
356 end 361 end
357 362
358 module:hook("muc-add-history", function (event) 363 module:hook("muc-add-history", function (event)
384 module:add_feature(xmlns_mam); 389 module:add_feature(xmlns_mam);
385 390
386 module:hook("muc-disco#info", function(event) 391 module:hook("muc-disco#info", function(event)
387 event.reply:tag("feature", {var=xmlns_mam}):up(); 392 event.reply:tag("feature", {var=xmlns_mam}):up();
388 end); 393 end);
394
395 -- Cleanup
396
397 local cleanup_after = module:get_option_string("muc_log_expires_after", "1w");
398 local cleanup_interval = module:get_option_number("muc_log_cleanup_interval", 4 * 60 * 60);
399
400 if cleanup_after ~= "never" then
401 local cleanup_storage = module:open_store("muc_log_cleanup");
402 local cleanup_map = module:open_store("muc_log_cleanup", "map");
403
404 local day = 86400;
405 local multipliers = { d = day, w = day * 7, m = 31 * day, y = 365.2425 * day };
406 local n, m = cleanup_after:lower():match("(%d+)%s*([dwmy]?)");
407 if not n then
408 module:log("error", "Could not parse muc_log_expires_after string %q", cleanup_after);
409 return false;
410 end
411
412 cleanup_after = tonumber(n) * ( multipliers[m] or 1 );
413
414 module:log("debug", "muc_log_expires_after = %d -- in seconds", cleanup_after);
415
416 if not archive.delete then
417 module:log("error", "muc_log_expires_after set but mod_%s does not support deleting", archive._provided_by);
418 return false;
419 end
420
421 -- For each day, store a set of rooms that have new messages. To expire
422 -- messages, we collect the union of sets of rooms from dates that fall
423 -- outside the cleanup range.
424
425 function schedule_cleanup(roomname, date)
426 cleanup_map:set(date or datestamp(), roomname, true);
427 end
428
429 cleanup_runner = require "util.async".runner(function ()
430 local rooms = {};
431 local cut_off = datestamp(os.time() - cleanup_after);
432 for date in cleanup_storage:users() do
433 if date <= cut_off then
434 module:log("debug", "Messages from %q should be expired", date);
435 local messages_this_day = cleanup_storage:get(date);
436 if messages_this_day then
437 for room in pairs(messages_this_day) do
438 rooms[room] = true;
439 end
440 if date < cut_off then
441 -- Messages from the same day as the cut-off might not have expired yet,
442 -- but all earlier will have, so clear storage for those days.
443 cleanup_storage:set(date, nil);
444 end
445 end
446 end
447 end
448 local sum, num_rooms = 0, 0;
449 for room in pairs(rooms) do
450 local ok, err = archive:delete(room, { ["end"] = os.time() - cleanup_after; })
451 if ok then
452 num_rooms = num_rooms + 1;
453 sum = sum + (tonumber(ok) or 0);
454 end
455 end
456 module:log("info", "Deleted %d expired messages for %d rooms", sum, num_rooms);
457 end);
458
459 cleanup_task = module:add_timer(1, function ()
460 cleanup_runner:run(true);
461 return cleanup_interval;
462 end);
463 else
464 module:log("debug", "Archive expiry disabled");
465 end