0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-16 08:58:20 +02:00

ircd:Ⓜ️:room::members: Simplify and improve interface; callsites.

This commit is contained in:
Jason Volk 2019-07-23 19:31:40 -07:00
parent 8787dcfaf7
commit eb3b4d82fb
7 changed files with 195 additions and 248 deletions

View file

@ -23,19 +23,18 @@ namespace ircd::m
///
struct ircd::m::room::members
{
using closure = std::function<void (const id::user &)>;
using closure_bool = std::function<bool (const id::user &)>;
using closure_idx = std::function<bool (const id::user &, const event::idx &)>;
using closure = std::function<bool (const id::user &)>;
static string_view membership(const mutable_buffer &out, const event::idx &);
static bool membership(const event::idx &, const string_view &);
m::room room;
bool for_each(const string_view &membership, const event::closure_bool &) const;
void for_each(const string_view &membership, const event::closure &) const;
bool for_each(const string_view &membership, const closure_bool &) const;
void for_each(const string_view &membership, const closure &) const;
bool for_each(const event::closure_bool &) const;
void for_each(const event::closure &) const;
bool for_each(const closure_bool &) const;
void for_each(const closure &) const;
bool for_each(const string_view &membership, const closure &) const;
bool for_each(const string_view &membership, const closure_idx &) const;
bool for_each(const closure &) const;
bool for_each(const closure_idx &) const;
bool empty(const string_view &membership) const;
bool empty() const;

View file

@ -3082,15 +3082,14 @@ const
};
room.fopts = &fopts;
const m::room::members members{room};
return members.for_each(membership, event::closure_bool{[&seen, &closure]
(const m::event &event)
const m::room::members members
{
const auto &other
{
at<"state_key"_>(event)
};
room
};
return members.for_each(membership, [&seen, &closure]
(const user::id &other)
{
const auto it
{
seen.lower_bound(other)
@ -3101,7 +3100,7 @@ const
seen.emplace_hint(it, std::string{other});
return closure(m::user{other});
}});
});
}});
}

View file

@ -1237,15 +1237,15 @@ const
{
user::id::buf ret;
const members members{*this};
members.for_each(membership, members::closure_bool{[&host, &ret]
(const id::user &user_id)
members.for_each(membership, [&host, &ret]
(const auto &user_id, const auto &event_idx)
{
if(host && user_id.host() != host)
return true;
ret = user_id;
return false;
}});
});
return ret;
}
@ -3068,57 +3068,16 @@ bool
ircd::m::room::members::empty()
const
{
const room::state state
{
room
};
// for_each() returns true when it reaches the end of the iteration.
return state.for_each("m.room.member", state::closure_bool{[]
(const auto &type, const auto &state_key, const auto &event_idx)
{
return false;
}});
return empty(string_view{});
}
bool
ircd::m::room::members::empty(const string_view &membership)
const
{
const room::state state
return for_each(membership, closure{[](const auto &)
{
room
};
// joined members optimization. Only possible when seeking
// membership="join" on the present state of the room.
if(membership == "join" && state.present())
{
// _for_each() returns true when it reaches the end of the iteration.
const room::origins origins{room};
return origins._for_each(origins, []
(const string_view &)
{
// closure returns false to break causing _for_each() to return false.
return false;
});
}
// for_each() returns true when it reaches the end of the iteration.
return state.for_each("m.room.member", state::closure_bool{[&membership]
(const auto &type, const auto &state_key, const auto &event_idx)
{
// return false if the query succeeds, breaking the iteration.
return !m::query(std::nothrow, event_idx, "content", [&membership]
(const json::object &content)
{
const json::string &content_membership
{
content["membership"]
};
return !membership || content_membership == membership;
});
return false;
}});
}
@ -3126,178 +3085,98 @@ size_t
ircd::m::room::members::count()
const
{
const room::state state
{
room
};
return state.count("m.room.member");
return count(string_view{});
}
size_t
ircd::m::room::members::count(const string_view &membership)
const
{
// Allow empty membership string to count all memberships
if(!membership)
return count();
// joined members optimization. Only possible when seeking
// membership="join" on the present state of the room.
if(membership == "join" && state{room}.present())
{
size_t ret{0};
const room::origins origins{room};
origins._for_each(origins, [&ret](const string_view &)
{
++ret;
return true;
});
return ret;
}
static const event::keys::include keys
{
"content",
};
const m::event::fetch::opts fopts
{
keys, room.fopts? room.fopts->gopts : db::gopts{}
};
const room::state state
{
room, &fopts
};
size_t ret{0};
state.for_each("m.room.member", event::closure{[&ret, &membership]
(const m::event &event)
this->for_each(membership, room::members::closure{[&ret]
(const id::user &)
{
ret += m::membership(event) == membership;
++ret;
return true;
}});
return ret;
}
void
ircd::m::room::members::for_each(const closure &closure)
const
{
for_each(string_view{}, closure);
}
bool
ircd::m::room::members::for_each(const closure_bool &closure)
ircd::m::room::members::for_each(const closure &closure)
const
{
return for_each(string_view{}, closure);
}
void
ircd::m::room::members::for_each(const event::closure &closure)
bool
ircd::m::room::members::for_each(const closure_idx &closure)
const
{
for_each(string_view{}, closure);
return for_each(string_view{}, closure);
}
bool
ircd::m::room::members::for_each(const event::closure_bool &closure)
ircd::m::room::members::for_each(const string_view &membership,
const closure_idx &closure)
const
{
const room::state state{room};
return state.for_each("m.room.member", event::closure_bool{[&closure]
(const m::event &event)
const m::room::state state
{
return closure(event);
}});
room
};
const bool present
{
state.present()
};
// joined members optimization. Only possible when seeking
// membership="join" on the present state of the room.
if(membership == "join" && present)
return this->for_each(membership, [&closure, &state, this]
(const id::user &member)
{
const auto event_idx
{
state.get(std::nothrow, "m.room.member", member)
};
assert(event_idx);
return event_idx?
closure(member, event_idx):
true;
});
return state.for_each("m.room.member", [this, &membership, &closure]
(const string_view &type, const string_view &state_key, const event::idx &event_idx)
{
return !membership || this->membership(event_idx, membership)?
closure(state_key, event_idx):
true;
});
}
void
bool
ircd::m::room::members::for_each(const string_view &membership,
const closure &closure)
const
{
for_each(membership, closure_bool{[&closure]
(const user::id &user_id)
const m::room::state state
{
closure(user_id);
return true;
}});
}
/// Iterate the mxid's of the users in the room, optionally with a specific
/// membership state. This query contains internal optimizations as the closure
/// only requires a user::id. The db::gopts set in the room.fopts pointer is
/// still used if provided.
bool
ircd::m::room::members::for_each(const string_view &membership,
const closure_bool &closure)
const
{
// Setup the list of event fields to fetch for the closure
static const event::keys::include keys
{
"state_key", "content",
room
};
// In this case the fetch opts isn't static so it can maintain the
// previously given db::gopts, but it will use our keys list.
const m::event::fetch::opts fopts
const bool present
{
keys, room.fopts? room.fopts->gopts : db::gopts{}
state.present()
};
// Stack-over the the current fetch opts with our new opts for this query,
// putting them back when we're finished. This requires a const_cast which
// should be okay here.
auto &room(const_cast<m::room &>(this->room));
const scope_restore theirs
{
room.fopts, &fopts
};
return for_each(membership, event::closure_bool{[&closure]
(const event &event)
{
const user::id &user_id
{
at<"state_key"_>(event)
};
return closure(user_id);
}});
}
void
ircd::m::room::members::for_each(const string_view &membership,
const event::closure &closure)
const
{
for_each(membership, event::closure_bool{[&closure]
(const m::event &event)
{
closure(event);
return true;
}});
}
bool
ircd::m::room::members::for_each(const string_view &membership,
const event::closure_bool &closure)
const
{
if(empty(membership))
return for_each(closure);
// joined members optimization. Only possible when seeking
// membership="join" on the present state of the room.
if(!room.event_id && membership == "join")
{
const room::origins origins{room};
return origins._for_each(origins, [&closure, this]
if(membership == "join" && present)
return room::origins::_for_each(room, [this, &closure]
(const string_view &key)
{
const string_view &member
@ -3305,26 +3184,49 @@ const
std::get<1>(dbs::room_joined_key(key))
};
bool ret{true};
room.get(std::nothrow, "m.room.member", member, event::closure{[&closure, &ret]
(const event &event)
{
ret = closure(event);
}});
return ret;
return closure(member);
});
}
return for_each(event::closure_bool{[&membership, &closure]
(const event &event)
return this->for_each(membership, [&closure]
(const auto &user_id, const auto &event_idx)
{
if(m::membership(event) == membership)
if(!closure(event))
return false;
return closure(user_id);
});
}
return true;
}});
bool
ircd::m::room::members::membership(const event::idx &event_idx,
const string_view &membership)
{
return m::query(std::nothrow, event_idx, "content", [&membership]
(const json::object &content)
{
const json::string &content_membership
{
content["membership"]
};
return content_membership && content_membership == membership;
});
}
ircd::string_view
ircd::m::room::members::membership(const mutable_buffer &out,
const event::idx &event_idx)
{
return m::query(std::nothrow, event_idx, "content", [&out]
(const json::object &content) -> string_view
{
const json::string &content_membership
{
content["membership"]
};
return strlcpy
{
out, content_membership
};
});
}
//

View file

@ -596,7 +596,7 @@ initialsync_room_ephemeral_events(client &client,
//TODO: We're skipping receipts from members who left so we enjoy the
//TODO: joined members optimizations. Need to figure out if anyone
//TODO: left in the synced timeline and include them manually.
members.for_each("join", m::room::members::closure{[&events, &room]
members.for_each("join", [&events, &room]
(const m::user &user)
{
const m::user::room user_room{user};
@ -644,7 +644,9 @@ initialsync_room_ephemeral_events(client &client,
};
}
});
}});
return true;
});
}
void

View file

@ -99,15 +99,23 @@ get__members(client &client,
room
};
members.for_each(membership, m::event::closure_bool{[&request, &chunk, &not_membership]
(const m::event &event)
members.for_each(membership, [&request, &chunk, &not_membership]
(const m::user::id &member, const m::event::idx &event_idx)
{
if(m::membership(event) == not_membership)
if(m::room::members::membership(event_idx, not_membership))
return true;
const m::event::fetch event
{
event_idx, std::nothrow
};
if(!event.valid)
return true;
chunk.append(event);
return true;
}});
});
return std::move(response);
}
@ -161,17 +169,9 @@ get__joined_members(client &client,
room
};
members.for_each("join", m::room::members::closure{[&joined, &room]
(const m::user::id &user_id)
members.for_each("join", [&joined, &room]
(const m::user::id &user_id, const m::event::idx &event_idx)
{
const m::event::idx &event_idx
{
room.get(std::nothrow, "m.room.member", user_id)
};
if(!event_idx)
return;
json::stack::object room_member
{
joined, user_id
@ -186,7 +186,9 @@ get__joined_members(client &client,
room_member, key, val
};
});
}});
return true;
});
return std::move(response);
}

View file

@ -8217,9 +8217,9 @@ console_cmd__room__members(opt &out, const string_view &line)
m::room_id(param.at(0))
};
const string_view membership
const string_view &membership
{
param.at(1, "join"_sv)
param[1]
};
const m::room room
@ -8232,14 +8232,30 @@ console_cmd__room__members(opt &out, const string_view &line)
room
};
const m::room::members::closure closure{[&out, &membership]
(const m::user::id &user_id)
if(membership)
{
out << std::setw(8) << std::left << membership
<< " " << user_id << std::endl;
}};
members.for_each(membership, [&out, &membership]
(const m::user::id &user_id)
{
out << std::setw(8) << std::left << membership
<< " " << user_id << std::endl;
return true;
});
return true;
}
members.for_each(membership, [&out]
(const m::user::id &user_id, const m::event::idx &event_idx)
{
char buf[32];
out << std::setw(8) << std::left << m::room::members::membership(buf, event_idx)
<< " " << user_id << std::endl;
return true;
});
members.for_each(membership, closure);
return true;
}
@ -8271,9 +8287,18 @@ console_cmd__room__members__events(opt &out, const string_view &line)
room
};
const auto closure{[&out](const m::event &event)
const auto closure{[&out](const auto &user_id, const auto &event_idx)
{
const m::event::fetch event
{
event_idx, std::nothrow
};
if(!event.valid)
return true;
out << pretty_oneline(event) << std::endl;
return true;
}};
members.for_each(membership, closure);
@ -8346,12 +8371,30 @@ console_cmd__room__members__origin(opt &out, const string_view &line)
};
members.for_each(membership, [&out, &origin]
(const m::event &event)
(const auto &user_id, const auto &event_idx)
{
if(json::get<"origin"_>(event) != origin)
return;
const bool same_origin
{
m::query(std::nothrow, event_idx, "origin", [&origin]
(const auto &_origin)
{
return _origin == origin;
})
};
if(!same_origin)
return true;
const m::event::fetch event
{
event_idx, std::nothrow
};
if(!event.valid)
return true;
out << pretty_oneline(event) << std::endl;
return true;
});
return true;
@ -8404,12 +8447,12 @@ console_cmd__room__members__read(opt &out, const string_view &line)
<< std::endl;
}};
const auto member_closure{[&room_id, event_closure]
(const m::event &event)
members.for_each(membership, [&room_id, &event_closure]
(const m::user::id &user_id, const m::event::idx &event_idx)
{
const m::user user
{
at<"state_key"_>(event)
user_id
};
static const m::event::fetch::opts fopts
@ -8429,9 +8472,9 @@ console_cmd__room__members__read(opt &out, const string_view &line)
};
user_room.get(std::nothrow, "ircd.read", room_id, event_closure);
}};
return true;
});
members.for_each(membership, member_closure);
return true;
}

View file

@ -75,7 +75,7 @@ _join_room__m_direct(const m::event &event,
m::user::id::buf other_person;
const m::room::members members{room};
members.for_each(m::room::members::closure_bool{[&user_id, &other_person]
members.for_each([&user_id, &other_person]
(const auto &other_id)
{
if(other_id == user_id)
@ -83,7 +83,7 @@ _join_room__m_direct(const m::event &event,
other_person = other_id;
return false;
}});
});
if(!other_person)
return;