Add experimental event expiration

Currently disabled by default.
This commit is contained in:
Nicolas Werner 2023-07-05 00:08:37 +02:00
parent dcb6c00708
commit ad6e4fef64
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
10 changed files with 475 additions and 32 deletions

View file

@ -1610,8 +1610,7 @@ std::atomic<bool> event_expiration_running = false;
void
utils::removeExpiredEvents()
{
// TODO(Nico): Add its own toggle...
if (!UserSettings::instance()->updateSpaceVias())
if (!UserSettings::instance()->expireEvents())
return;
if (event_expiration_running.exchange(true)) {
@ -1645,18 +1644,20 @@ utils::removeExpiredEvents()
std::string currentRoom;
std::uint64_t currentRoomCount = 0;
std::string currentRoomPrevToken;
std::set<std::pair<std::string, std::string>> currentRoomStateEvents;
std::vector<std::string> currentRoomRedactionQueue;
mtx::events::account_data::nheko_extensions::EventExpiry currentExpiry;
static void next(std::shared_ptr<ApplyEventExpiration> state)
{
if (!state->currentRoomRedactionQueue.empty()) {
auto evid = state->currentRoomRedactionQueue.back();
auto room = state->currentRoom;
http::client()->redact_event(
state->currentRoom,
state->currentRoomRedactionQueue.back(),
[state = std::move(state)](const mtx::responses::EventId &,
mtx::http::RequestErr e) mutable {
const auto &event_id = state->currentRoomRedactionQueue.back();
room,
evid,
[state = std::move(state), evid](const mtx::responses::EventId &,
mtx::http::RequestErr e) mutable {
if (e) {
if (e->status_code == 429 && e->matrix_error.retry_after.count() != 0) {
ChatPage::instance()->callFunctionOnGuiThread(
@ -1669,17 +1670,19 @@ utils::removeExpiredEvents()
});
});
return;
} else {
nhlog::net()->error("Failed to redact event {} in {}: {}",
evid,
state->currentRoom,
*e);
state->currentRoomRedactionQueue.pop_back();
next(std::move(state));
}
nhlog::net()->error("Failed to redact event {} in {}: {}",
event_id,
state->currentRoom,
*e);
} else {
nhlog::net()->info("Redacted event {} in {}", evid, state->currentRoom);
state->currentRoomRedactionQueue.pop_back();
next(std::move(state));
}
nhlog::net()->info(
"Redacted event {} in {}: {}", event_id, state->currentRoom, *e);
state->currentRoomRedactionQueue.pop_back();
next(std::move(state));
});
} else if (!state->currentRoom.empty()) {
mtx::http::MessagesOpts opts{};
@ -1687,6 +1690,7 @@ utils::removeExpiredEvents()
opts.from = state->currentRoomPrevToken;
opts.limit = 1000;
opts.filter = state->filter;
opts.room_id = state->currentRoom;
http::client()->messages(
opts,
@ -1708,6 +1712,19 @@ utils::removeExpiredEvents()
mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(e))
continue;
if (std::holds_alternative<
mtx::events::RoomEvent<mtx::events::msg::Redacted>>(e))
continue;
if (std::holds_alternative<
mtx::events::StateEvent<mtx::events::msg::Redacted>>(e))
continue;
// skip events we don't know to protect us from mistakes.
if (std::holds_alternative<
mtx::events::RoomEvent<mtx::events::Unknown>>(e))
continue;
if (mtx::accessors::sender(e) != us)
continue;
@ -1720,6 +1737,21 @@ utils::removeExpiredEvents()
mtx::accessors::is_state_event(e))
continue;
if (mtx::accessors::is_state_event(e)) {
// skip the first state event of a type
if (std::visit(
[&state](const auto &se) {
if constexpr (requires { se.state_key; })
return state->currentRoomStateEvents
.emplace(to_string(se.type), se.state_key)
.second;
else
return false;
},
e))
continue;
}
if (state->currentExpiry.keep_only_latest &&
state->currentRoomCount > state->currentExpiry.keep_only_latest) {
state->currentRoomRedactionQueue.push_back(
@ -1738,6 +1770,7 @@ utils::removeExpiredEvents()
state->currentRoom.clear();
state->currentRoomCount = 0;
state->currentRoomPrevToken.clear();
state->currentRoomStateEvents.clear();
}
next(std::move(state));
@ -1764,20 +1797,11 @@ utils::removeExpiredEvents()
auto asus = std::make_shared<ApplyEventExpiration>();
asus->filter =
nlohmann::json{
"room",
nlohmann::json::object({
{
"timeline",
nlohmann::json::object({
{"senders", nlohmann::json::array({us})},
{"not_types", nlohmann::json::array({"m.room.redaction"})},
}),
},
}),
}
.dump();
nlohmann::json filter;
filter["timeline"]["senders"] = nlohmann::json::array({us});
filter["timeline"]["not_types"] = nlohmann::json::array({"m.room.redaction"});
asus->filter = filter.dump();
asus->globalExpiry = getExpEv();