0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-09-26 18:38:52 +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 struct ircd::m::room::members
{ {
using closure = std::function<void (const id::user &)>; using closure_idx = std::function<bool (const id::user &, const event::idx &)>;
using closure_bool = std::function<bool (const id::user &)>; 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; m::room room;
bool for_each(const string_view &membership, const event::closure_bool &) const; bool for_each(const string_view &membership, const closure &) const;
void for_each(const string_view &membership, const event::closure &) const; bool for_each(const string_view &membership, const closure_idx &) const;
bool for_each(const string_view &membership, const closure_bool &) const; bool for_each(const closure &) const;
void for_each(const string_view &membership, const closure &) const; bool for_each(const closure_idx &) 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 empty(const string_view &membership) const; bool empty(const string_view &membership) const;
bool empty() const; bool empty() const;

View file

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

View file

@ -1237,15 +1237,15 @@ const
{ {
user::id::buf ret; user::id::buf ret;
const members members{*this}; const members members{*this};
members.for_each(membership, members::closure_bool{[&host, &ret] members.for_each(membership, [&host, &ret]
(const id::user &user_id) (const auto &user_id, const auto &event_idx)
{ {
if(host && user_id.host() != host) if(host && user_id.host() != host)
return true; return true;
ret = user_id; ret = user_id;
return false; return false;
}}); });
return ret; return ret;
} }
@ -3068,57 +3068,16 @@ bool
ircd::m::room::members::empty() ircd::m::room::members::empty()
const const
{ {
const room::state state return empty(string_view{});
{
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;
}});
} }
bool bool
ircd::m::room::members::empty(const string_view &membership) ircd::m::room::members::empty(const string_view &membership)
const const
{ {
const room::state state return for_each(membership, closure{[](const auto &)
{ {
room return false;
};
// 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;
});
}}); }});
} }
@ -3126,178 +3085,98 @@ size_t
ircd::m::room::members::count() ircd::m::room::members::count()
const const
{ {
const room::state state return count(string_view{});
{
room
};
return state.count("m.room.member");
} }
size_t size_t
ircd::m::room::members::count(const string_view &membership) ircd::m::room::members::count(const string_view &membership)
const 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}; size_t ret{0};
state.for_each("m.room.member", event::closure{[&ret, &membership] this->for_each(membership, room::members::closure{[&ret]
(const m::event &event) (const id::user &)
{ {
ret += m::membership(event) == membership; ++ret;
return true;
}}); }});
return ret; return ret;
} }
void
ircd::m::room::members::for_each(const closure &closure)
const
{
for_each(string_view{}, closure);
}
bool bool
ircd::m::room::members::for_each(const closure_bool &closure) ircd::m::room::members::for_each(const closure &closure)
const const
{ {
return for_each(string_view{}, closure); return for_each(string_view{}, closure);
} }
void bool
ircd::m::room::members::for_each(const event::closure &closure) ircd::m::room::members::for_each(const closure_idx &closure)
const const
{ {
for_each(string_view{}, closure); return for_each(string_view{}, closure);
} }
bool 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
{ {
const room::state state{room}; const m::room::state state
return state.for_each("m.room.member", event::closure_bool{[&closure]
(const m::event &event)
{ {
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, ircd::m::room::members::for_each(const string_view &membership,
const closure &closure) const closure &closure)
const const
{ {
for_each(membership, closure_bool{[&closure] const m::room::state state
(const user::id &user_id)
{ {
closure(user_id); room
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",
}; };
// In this case the fetch opts isn't static so it can maintain the const bool present
// previously given db::gopts, but it will use our keys list.
const m::event::fetch::opts fopts
{ {
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 // joined members optimization. Only possible when seeking
// membership="join" on the present state of the room. // membership="join" on the present state of the room.
if(!room.event_id && membership == "join") if(membership == "join" && present)
{ return room::origins::_for_each(room, [this, &closure]
const room::origins origins{room};
return origins._for_each(origins, [&closure, this]
(const string_view &key) (const string_view &key)
{ {
const string_view &member const string_view &member
@ -3305,26 +3184,49 @@ const
std::get<1>(dbs::room_joined_key(key)) std::get<1>(dbs::room_joined_key(key))
}; };
bool ret{true}; return closure(member);
room.get(std::nothrow, "m.room.member", member, event::closure{[&closure, &ret]
(const event &event)
{
ret = closure(event);
}});
return ret;
}); });
}
return for_each(event::closure_bool{[&membership, &closure] return this->for_each(membership, [&closure]
(const event &event) (const auto &user_id, const auto &event_idx)
{ {
if(m::membership(event) == membership) return closure(user_id);
if(!closure(event)) });
return false; }
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: We're skipping receipts from members who left so we enjoy the
//TODO: joined members optimizations. Need to figure out if anyone //TODO: joined members optimizations. Need to figure out if anyone
//TODO: left in the synced timeline and include them manually. //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 &user)
{ {
const m::user::room user_room{user}; const m::user::room user_room{user};
@ -644,7 +644,9 @@ initialsync_room_ephemeral_events(client &client,
}; };
} }
}); });
}});
return true;
});
} }
void void

View file

@ -99,15 +99,23 @@ get__members(client &client,
room room
}; };
members.for_each(membership, m::event::closure_bool{[&request, &chunk, &not_membership] members.for_each(membership, [&request, &chunk, &not_membership]
(const m::event &event) (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; return true;
chunk.append(event); chunk.append(event);
return true; return true;
}}); });
return std::move(response); return std::move(response);
} }
@ -161,17 +169,9 @@ get__joined_members(client &client,
room room
}; };
members.for_each("join", m::room::members::closure{[&joined, &room] members.for_each("join", [&joined, &room]
(const m::user::id &user_id) (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 json::stack::object room_member
{ {
joined, user_id joined, user_id
@ -186,7 +186,9 @@ get__joined_members(client &client,
room_member, key, val room_member, key, val
}; };
}); });
}});
return true;
});
return std::move(response); 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)) 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 const m::room room
@ -8232,14 +8232,30 @@ console_cmd__room__members(opt &out, const string_view &line)
room room
}; };
const m::room::members::closure closure{[&out, &membership] if(membership)
(const m::user::id &user_id)
{ {
out << std::setw(8) << std::left << membership members.for_each(membership, [&out, &membership]
<< " " << user_id << std::endl; (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; return true;
} }
@ -8271,9 +8287,18 @@ console_cmd__room__members__events(opt &out, const string_view &line)
room 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; out << pretty_oneline(event) << std::endl;
return true;
}}; }};
members.for_each(membership, closure); 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] members.for_each(membership, [&out, &origin]
(const m::event &event) (const auto &user_id, const auto &event_idx)
{ {
if(json::get<"origin"_>(event) != origin) const bool same_origin
return; {
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; out << pretty_oneline(event) << std::endl;
return true;
}); });
return true; return true;
@ -8404,12 +8447,12 @@ console_cmd__room__members__read(opt &out, const string_view &line)
<< std::endl; << std::endl;
}}; }};
const auto member_closure{[&room_id, event_closure] members.for_each(membership, [&room_id, &event_closure]
(const m::event &event) (const m::user::id &user_id, const m::event::idx &event_idx)
{ {
const m::user user const m::user user
{ {
at<"state_key"_>(event) user_id
}; };
static const m::event::fetch::opts fopts 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); user_room.get(std::nothrow, "ircd.read", room_id, event_closure);
}}; return true;
});
members.for_each(membership, member_closure);
return true; return true;
} }

View file

@ -75,7 +75,7 @@ _join_room__m_direct(const m::event &event,
m::user::id::buf other_person; m::user::id::buf other_person;
const m::room::members members{room}; 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) (const auto &other_id)
{ {
if(other_id == user_id) if(other_id == user_id)
@ -83,7 +83,7 @@ _join_room__m_direct(const m::event &event,
other_person = other_id; other_person = other_id;
return false; return false;
}}); });
if(!other_person) if(!other_person)
return; return;