diff --git a/include/ircd/m/dbs/appendix.h b/include/ircd/m/dbs/appendix.h index 0c74fac20..c08b2665a 100644 --- a/include/ircd/m/dbs/appendix.h +++ b/include/ircd/m/dbs/appendix.h @@ -54,6 +54,9 @@ enum ircd::m::dbs::appendix::index /// properly complete the event_refs graph to all the referencing events. EVENT_HORIZON, + /// Resolves unresolved references for this event left in event_horizon. + EVENT_HORIZON_RESOLVE, + /// Involves the event_sender column (reverse index on the event sender). EVENT_SENDER, @@ -108,6 +111,7 @@ namespace ircd::m::dbs string_view _index_room(db::txn &, const event &, const write_opts &); void _index_event_type(db::txn &, const event &, const write_opts &); void _index_event_sender(db::txn &, const event &, const write_opts &); + void _index_event_horizon_resolve(db::txn &, const event &, const write_opts &); void _index_event_horizon(db::txn &, const event &, const write_opts &, const id::event &); void _index_event_refs_m_room_redaction(db::txn &, const event &, const write_opts &); void _index_event_refs_m_receipt_m_read(db::txn &, const event &, const write_opts &); diff --git a/include/ircd/m/dbs/write_opts.h b/include/ircd/m/dbs/write_opts.h index 5a5e0bae0..17039ec64 100644 --- a/include/ircd/m/dbs/write_opts.h +++ b/include/ircd/m/dbs/write_opts.h @@ -41,6 +41,10 @@ struct ircd::m::dbs::write_opts /// by clearing a bit. std::bitset<256> event_refs {event_refs_all}; + /// Selection of what reference types to resolve and delete from the + /// event_horizon for this event. + std::bitset<256> horizon_resolve {event_refs_all}; + /// Whether the present state table `room_state` should be updated by /// this operation if appropriate. bool present {true}; diff --git a/ircd/m_dbs.cc b/ircd/m_dbs.cc index 7117ea4b0..2860b9a67 100644 --- a/ircd/m_dbs.cc +++ b/ircd/m_dbs.cc @@ -271,6 +271,9 @@ ircd::m::dbs::_index_event(db::txn &txn, if(opts.appendix.test(appendix::EVENT_JSON)) _index_event_json(txn, event, opts); + if(opts.appendix.test(appendix::EVENT_HORIZON_RESOLVE) && opts.horizon_resolve.any()) + _index_event_horizon_resolve(txn, event, opts); + if(opts.appendix.test(appendix::EVENT_REFS) && opts.event_refs.any()) _index_event_refs(txn, event, opts); @@ -827,6 +830,7 @@ ircd::m::dbs::_index_event_horizon(db::txn &txn, const m::event::id &unresolved_id) { thread_local char buf[EVENT_HORIZON_KEY_MAX_SIZE]; + assert(opts.appendix.test(appendix::EVENT_HORIZON)); assert(opts.event_idx != 0 && unresolved_id); const string_view &key { @@ -842,6 +846,75 @@ ircd::m::dbs::_index_event_horizon(db::txn &txn, }; } +void +ircd::m::dbs::_index_event_horizon_resolve(db::txn &txn, + const event &event, + const write_opts &opts) +{ + thread_local char buf[EVENT_HORIZON_KEY_MAX_SIZE]; + assert(opts.appendix.test(appendix::EVENT_HORIZON_RESOLVE)); + assert(opts.event_idx != 0); + const string_view &key + { + event_horizon_key(buf, at<"event_id"_>(event), 0UL) + }; + + auto it + { + dbs::event_horizon.begin(key) + }; + + for(; it; ++it) + { + const auto parts + { + event_horizon_key(it->first) + }; + + const auto &event_idx + { + std::get<0>(parts) + }; + + assert(event_idx != opts.event_idx); + const event::fetch _event + { + event_idx, std::nothrow + }; + + if(!_event.valid) + continue; + + // Make the references on behalf of the future event + write_opts _opts; + _opts.op = opts.op; + _opts.event_idx = event_idx; + _opts.appendix.reset(); + _opts.appendix.set(appendix::EVENT); + _opts.appendix.set(appendix::EVENT_REFS); + _opts.event_refs = opts.horizon_resolve; + write(txn, _event, _opts); + + // Delete the event_horizon entry after resolving. + thread_local char buf[EVENT_HORIZON_KEY_MAX_SIZE]; + const string_view &key + { + event_horizon_key(buf, at<"event_id"_>(event), event_idx) + }; + + db::txn::append + { + txn, dbs::event_horizon, + { + opts.op == db::op::SET? + db::op::DELETE: + db::op::SET, + key + } + }; + } +} + void ircd::m::dbs::_index_event_sender(db::txn &txn, const event &event, diff --git a/modules/console.cc b/modules/console.cc index fb9496da0..42d921a7b 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -6416,6 +6416,48 @@ console_cmd__event__bad(opt &out, const string_view &line) return true; } +bool +console_cmd__event__horizon(opt &out, const string_view &line) +{ + const params param{line, " ", + { + "event_id", + }}; + + const m::event::id &event_id + { + param.at("event_id") + }; + + char buf[m::dbs::EVENT_HORIZON_KEY_MAX_SIZE]; + const string_view &key + { + m::dbs::event_horizon_key(buf, event_id, 0UL) + }; + + for(auto it(m::dbs::event_horizon.begin(key)); it; ++it) + { + const auto &event_idx + { + std::get<0>(m::dbs::event_horizon_key(it->first)) + }; + + const auto _event_id + { + m::event_id(event_idx, std::nothrow) + }; + + out << event_id + << " -> " + << event_idx + << " " + << _event_id + << std::endl; + } + + return true; +} + bool console_cmd__event__cached(opt &out, const string_view &line) {