add archive_expires_after option

This commit is contained in:
Luca Matei Pintilie
2026-01-10 18:59:34 +01:00
committed by mathieui
parent 4de88b5160
commit 6ed185a8a5
11 changed files with 249 additions and 0 deletions
+9
View File
@@ -2,6 +2,7 @@
#ifdef USE_DATABASE
#include <database/select_query.hpp>
#include <database/delete_query.hpp>
#include <database/save.hpp>
#include <database/database.hpp>
#include <utils/get_first_non_empty.hpp>
@@ -317,6 +318,14 @@ std::vector<Database::RosterItem> Database::get_full_roster()
return query.execute(*Database::db);
}
void Database::delete_old_muclines(const long& seconds)
{
auto query = DeleteQuery(Database::muc_log_lines.get_name());
query << " WHERE " << Database::Date{} << "<" << seconds;
query.execute(*Database::db);
}
void Database::close()
{
Database::db = nullptr;
+1
View File
@@ -153,6 +153,7 @@ class Database
static void delete_roster_item(const std::string& local, const std::string& remote);
static std::vector<Database::RosterItem> get_contact_list(const std::string& local);
static std::vector<Database::RosterItem> get_full_roster();
static void delete_old_muclines(const long& seconds);
static void close();
static void open(const std::string& filename);
+3
View File
@@ -14,6 +14,7 @@
#include <csignal>
#include <identd/identd_server.hpp>
#include <scheduler/scheduler.hpp>
// A flag set by the SIGINT signal handler.
static std::atomic<bool> stop(false);
@@ -107,6 +108,7 @@ static int main_loop(std::string hostname, std::string password)
if (Config::get_int("identd_port", 113) != 0)
identd = std::make_unique<IdentdServer>(*xmpp_component, p, static_cast<uint16_t>(Config::get_int("identd_port", 113)));
Scheduler::start_scheduler();
auto timeout = TimedEventsManager::instance().get_timeout();
while (p->poll(timeout) != -1)
{
@@ -130,6 +132,7 @@ static int main_loop(std::string hostname, std::string password)
#endif
if (identd)
identd->shutdown();
Scheduler::stop_scheduler();
// Cancel the timer for a potential reconnection
TimedEventsManager::instance().cancel("XMPP reconnection");
}
+68
View File
@@ -0,0 +1,68 @@
#include "biboumi.h"
#include <config/config.hpp>
#include <scheduler/scheduler.hpp>
#include <utils/parse_duration.hpp>
#include <utils/timed_events.hpp>
#ifdef USE_DATABASE
#include <database/database.hpp>
#endif
static const std::unordered_map<
std::string, std::pair<std::chrono::seconds, std::function<void()>>>
events = {
#ifdef USE_DATABASE
{"cleanup_old_messages",
{60s * 10 /* 10min */, &Scheduler::cleanup_old_messages}},
#endif
};
void Scheduler::start_scheduler() {
for (const auto &job : events) {
const std::string name = job.first;
const std::chrono::seconds interval = job.second.first;
const std::function<void()> job_function = job.second.second;
// Run it once at startup
job_function();
// Then every interval
TimedEventsManager::instance().add_event(
TimedEvent(interval, job_function, name));
}
}
void Scheduler::stop_scheduler() {
for (const auto &job : events) {
const std::string name = job.first;
TimedEventsManager::instance().cancel(name);
}
}
#ifdef USE_DATABASE
void Scheduler::cleanup_old_messages() {
// Get the config value
const std::string archive_expires_after =
Config::get("archive_expires_after", "0");
const std::optional<long> seconds =
utils::parse_duration(archive_expires_after);
// If it's actually set and relevant, start cleanup
if (seconds.has_value() && seconds.value() != 0) {
// Calculate age of messages to be deleted
log_debug("[cleanup_old_messages] Deleting messages older than ",
archive_expires_after, " (", seconds.value(), " seconds)");
// Convert the config value to a duration
const auto duration = std::chrono::duration<long>(seconds.value());
// Get timestamp now relative to unix epoch
const auto now = std::chrono::system_clock::now();
// Older than this get deleted
const auto ago = now - duration;
// Convert to seconds since epoch
const auto since_epoch = std::chrono::duration_cast<std::chrono::seconds>(
ago.time_since_epoch());
Database::delete_old_muclines(since_epoch.count());
} else
log_debug("[cleanup_old_messages] Not deleting anything. "
"archive_expires_after is ",
archive_expires_after);
}
#endif
+10
View File
@@ -0,0 +1,10 @@
#pragma once
class Scheduler {
public:
static void start_scheduler();
static void stop_scheduler();
// Jobs
static void cleanup_old_messages();
};
+36
View File
@@ -0,0 +1,36 @@
#include <cstdio>
#include <optional>
#include <stdexcept>
#include <string>
#include <unordered_map>
#include <utils/parse_duration.hpp>
namespace utils {
// Strongly inspired from prosody
// https://hg.prosody.im/trunk/file/0ff11f2e87cd/util/human/io.lua#l214
static const long day = 86400;
static const std::unordered_map<std::string, long> multipliers = {
{"d", day}, {"w", day * 7}, {"mon", day * 31}, {"y", day * 365.2425},
{"s", 1}, {"min", 60}, {"h", 3600}, {"ho", 3600},
};
std::optional<long> parse_duration(const std::string &duration) {
std::size_t ptr;
long number;
try {
number = std::stol(duration, &ptr, 10);
} catch (std::invalid_argument &) {
return {};
}
const std::string m = duration.substr(ptr);
if (!multipliers.contains(m))
return {};
const long multiplier = multipliers.at(m);
return multiplier * number;
}
} // namespace utils
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include <optional>
#include <string>
namespace utils {
std::optional<long> parse_duration(const std::string &duration);
} // namespace utils