diff --git a/include/ircd/m/room/state.h b/include/ircd/m/room/state.h index 120afeeb6..41b96e8f6 100644 --- a/include/ircd/m/room/state.h +++ b/include/ircd/m/room/state.h @@ -108,4 +108,5 @@ struct ircd::m::room::state static size_t rebuild_history(const state &); static size_t rebuild_present(const state &); static bool force_present(const event &); + static size_t purge_replaced(const state &); }; diff --git a/ircd/m.cc b/ircd/m.cc index f810fb135..85eeb69bf 100644 --- a/ircd/m.cc +++ b/ircd/m.cc @@ -4049,6 +4049,19 @@ ircd::m::room::purge(const room &room) return call(room); } +size_t +ircd::m::room::state::purge_replaced(const state &state) +{ + using prototype = size_t (const room::state &); + + static mods::import call + { + "m_room", "ircd::m::room::state::purge_replaced" + }; + + return call(state); +} + bool ircd::m::room::state::force_present(const event &event) { diff --git a/modules/console.cc b/modules/console.cc index cc27ac831..dba7a5ee5 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -7512,6 +7512,33 @@ console_cmd__room__state__force(opt &out, const string_view &line) return true; } +bool +console_cmd__room__state__purge__replaced(opt &out, const string_view &line) +{ + const params param{line, " ", + { + "room_id", + }}; + + const auto &room_id + { + m::room_id(param.at(0)) + }; + + const m::room::state state + { + room_id + }; + + const size_t ret + { + m::room::state::purge_replaced(state) + }; + + out << "erased " << ret << std::endl; + return true; +} + bool console_cmd__room__state__rebuild__present(opt &out, const string_view &line) { diff --git a/modules/m_room.cc b/modules/m_room.cc index fab2ff3f0..8c131de57 100644 --- a/modules/m_room.cc +++ b/modules/m_room.cc @@ -561,6 +561,39 @@ ircd::m::is_complete(const room &room) return { true, depth }; } +size_t +IRCD_MODULE_EXPORT +ircd::m::room::state::purge_replaced(const state &state) +{ + db::txn txn + { + *m::dbs::events + }; + + size_t ret(0); + m::room::messages it + { + state.room_id, uint64_t(0) + }; + + if(!it) + return ret; + + for(; it; ++it) + { + const m::event::idx &event_idx(it.event_idx()); + if(!m::get(std::nothrow, event_idx, "state_key", [](const auto &) {})) + continue; + + if(!m::event::refs(event_idx).count(m::dbs::ref::STATE)) + continue; + + // TODO: erase event + } + + return ret; +} + bool IRCD_MODULE_EXPORT ircd::m::room::state::force_present(const m::event &event)