mirror of
https://github.com/matrix-construct/construct
synced 2024-12-27 07:54:05 +01:00
modules/s_fetch: Split hook handler into auth and prev related subroutines.
This commit is contained in:
parent
4a22071be3
commit
a5f26db7ea
3 changed files with 178 additions and 137 deletions
|
@ -259,8 +259,14 @@ struct ircd::m::vm::opts
|
|||
/// evaluation.
|
||||
bool fetch_prev_wait {true};
|
||||
|
||||
/// Throws fault::EVENT if *all* of the prev_events do not exist locally.
|
||||
/// This is used to enforce that at least one path is traversable. This
|
||||
/// test is conducted after waiting if fetch_prev and fetch_prev_wait.
|
||||
bool fetch_prev_any {true};
|
||||
|
||||
/// Throws fault::EVENT if *any* of the prev_events do not exist locally.
|
||||
/// This is used to enforce that all references have been acquired.
|
||||
/// This is used to enforce that all references have been acquired; other
|
||||
/// corollary conditions are similar to fetch_prev_any.
|
||||
bool fetch_prev_all {false};
|
||||
|
||||
/// Evaluators can set this value to optimize the creation of the database
|
||||
|
|
|
@ -40,7 +40,7 @@ ircd::m::fetch::auth_timeout
|
|||
decltype(ircd::m::fetch::hook)
|
||||
ircd::m::fetch::hook
|
||||
{
|
||||
hook_handler,
|
||||
hook_handle,
|
||||
{
|
||||
{ "_site", "vm.fetch" }
|
||||
}
|
||||
|
@ -98,16 +98,13 @@ ircd::m::fetch::fini()
|
|||
//
|
||||
|
||||
void
|
||||
ircd::m::fetch::hook_handler(const event &event,
|
||||
ircd::m::fetch::hook_handle(const event &event,
|
||||
vm::eval &eval)
|
||||
try
|
||||
{
|
||||
assert(eval.opts);
|
||||
assert(eval.opts->fetch);
|
||||
const auto &opts
|
||||
{
|
||||
*eval.opts
|
||||
};
|
||||
const auto &opts{*eval.opts};
|
||||
|
||||
const auto &type
|
||||
{
|
||||
|
@ -130,140 +127,24 @@ try
|
|||
m::room room{room_id};
|
||||
room.event_id = event_id;
|
||||
|
||||
const event::prev prev
|
||||
{
|
||||
*eval.event_
|
||||
};
|
||||
evaltab tab;
|
||||
if(opts.fetch_auth_check)
|
||||
hook_handle_auth(event, eval, tab, room);
|
||||
|
||||
const size_t auth_count
|
||||
{
|
||||
size(json::get<"auth_events"_>(prev))
|
||||
};
|
||||
|
||||
size_t auth_exists(0);
|
||||
if(opts.fetch_auth_check) for(size_t i(0); i < auth_count; ++i)
|
||||
{
|
||||
const auto &auth_id
|
||||
{
|
||||
prev.auth_event(i)
|
||||
};
|
||||
|
||||
if(m::exists(auth_id))
|
||||
{
|
||||
++auth_exists;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(opts.fetch_auth_check && auth_exists < auth_count)
|
||||
{
|
||||
log::dwarning
|
||||
{
|
||||
log, "%s %s auth_events:%zu hit:%zu miss:%zu",
|
||||
loghead(eval),
|
||||
at<"event_id"_>(event),
|
||||
auth_count,
|
||||
auth_exists,
|
||||
auth_count - auth_exists,
|
||||
};
|
||||
|
||||
const net::hostport remote
|
||||
{
|
||||
eval.opts->node_id?
|
||||
eval.opts->node_id:
|
||||
!my_host(json::get<"origin"_>(event))?
|
||||
string_view(json::get<"origin"_>(event)):
|
||||
string_view{}
|
||||
};
|
||||
|
||||
if(!opts.fetch_auth || !bool(m::fetch::enable) || !remote)
|
||||
throw vm::error
|
||||
{
|
||||
vm::fault::EVENT, "Failed to fetch auth_events for %s in %s",
|
||||
json::get<"event_id"_>(*eval.event_),
|
||||
json::get<"room_id"_>(*eval.event_)
|
||||
};
|
||||
|
||||
auth_chain(room, remote);
|
||||
auth_exists = auth_count;
|
||||
}
|
||||
|
||||
const size_t prev_count
|
||||
{
|
||||
size(json::get<"prev_events"_>(prev))
|
||||
};
|
||||
|
||||
size_t prev_exists(0), prev_fetching(0);
|
||||
if(opts.fetch_prev_check) for(size_t i(0); i < prev_count; ++i)
|
||||
{
|
||||
const auto &prev_id
|
||||
{
|
||||
prev.prev_event(i)
|
||||
};
|
||||
|
||||
if(m::exists(prev_id))
|
||||
{
|
||||
++prev_exists;
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool can_fetch
|
||||
{
|
||||
opts.fetch_prev && bool(m::fetch::enable)
|
||||
};
|
||||
|
||||
const bool fetching
|
||||
{
|
||||
can_fetch && start(room_id, prev_id)
|
||||
};
|
||||
|
||||
prev_fetching += fetching;
|
||||
}
|
||||
|
||||
size_t prev_fetched(0);
|
||||
if(prev_fetching && opts.fetch_prev_wait) for(size_t i(0); i < prev_count; ++i)
|
||||
{
|
||||
const auto &prev_id
|
||||
{
|
||||
prev.prev_event(i)
|
||||
};
|
||||
|
||||
dock.wait([&prev_id]
|
||||
{
|
||||
return !requests.count(prev_id);
|
||||
});
|
||||
|
||||
prev_fetched += m::exists(prev_id);
|
||||
}
|
||||
if(opts.fetch_prev_check)
|
||||
hook_handle_prev(event, eval, tab, room);
|
||||
|
||||
log::debug
|
||||
{
|
||||
log, "%s %s %s ac:%zu ae:%zu pc:%zu pe:%zu pf:%zu",
|
||||
loghead(eval),
|
||||
json::get<"event_id"_>(*eval.event_),
|
||||
json::get<"room_id"_>(*eval.event_),
|
||||
auth_count,
|
||||
auth_exists,
|
||||
prev_count,
|
||||
prev_exists,
|
||||
prev_fetched,
|
||||
};
|
||||
|
||||
if(opts.fetch_prev_check && opts.fetch_prev_wait && prev_exists + prev_fetched == 0)
|
||||
throw vm::error
|
||||
{
|
||||
vm::fault::EVENT, "Failed to fetch any prev_events for %s in %s",
|
||||
json::get<"event_id"_>(*eval.event_),
|
||||
json::get<"room_id"_>(*eval.event_)
|
||||
};
|
||||
|
||||
if(opts.fetch_prev_check && opts.fetch_prev_wait && opts.fetch_prev_all && prev_exists + prev_fetched < prev_count)
|
||||
throw vm::error
|
||||
{
|
||||
vm::fault::EVENT, "Failed to fetch all %zu required prev_events for %s in %s",
|
||||
prev_count,
|
||||
json::get<"event_id"_>(*eval.event_),
|
||||
json::get<"room_id"_>(*eval.event_)
|
||||
json::get<"event_id"_>(event),
|
||||
json::get<"room_id"_>(event),
|
||||
tab.auth_count,
|
||||
tab.auth_exists,
|
||||
tab.prev_count,
|
||||
tab.prev_exists,
|
||||
tab.prev_fetched,
|
||||
};
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
|
@ -279,6 +160,147 @@ catch(const std::exception &e)
|
|||
throw;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::fetch::hook_handle_auth(const event &event,
|
||||
vm::eval &eval,
|
||||
evaltab &tab,
|
||||
const room &room)
|
||||
|
||||
{
|
||||
const auto &opts{*eval.opts};
|
||||
const event::prev prev{event};
|
||||
tab.auth_count = size(json::get<"auth_events"_>(prev));
|
||||
for(size_t i(0); i < tab.auth_count; ++i)
|
||||
{
|
||||
const auto &auth_id
|
||||
{
|
||||
prev.auth_event(i)
|
||||
};
|
||||
|
||||
tab.auth_exists += bool(m::exists(auth_id));
|
||||
}
|
||||
|
||||
assert(tab.auth_exists <= tab.auth_count);
|
||||
if(tab.auth_exists == tab.auth_count)
|
||||
return;
|
||||
|
||||
log::dwarning
|
||||
{
|
||||
log, "%s %s auth_events:%zu hit:%zu miss:%zu",
|
||||
loghead(eval),
|
||||
at<"event_id"_>(event),
|
||||
tab.auth_count,
|
||||
tab.auth_exists,
|
||||
tab.auth_count - tab.auth_exists,
|
||||
};
|
||||
|
||||
const net::hostport remote
|
||||
{
|
||||
opts.node_id?
|
||||
opts.node_id:
|
||||
!my_host(json::get<"origin"_>(event))?
|
||||
string_view(json::get<"origin"_>(event)):
|
||||
string_view{}
|
||||
};
|
||||
|
||||
if(!opts.fetch_auth || !bool(m::fetch::enable) || !remote)
|
||||
throw vm::error
|
||||
{
|
||||
vm::fault::EVENT, "Failed to fetch auth_events for %s in %s",
|
||||
json::get<"event_id"_>(event),
|
||||
json::get<"room_id"_>(event)
|
||||
};
|
||||
|
||||
auth_chain(room, remote);
|
||||
tab.auth_exists = tab.auth_count;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::fetch::hook_handle_prev(const event &event,
|
||||
vm::eval &eval,
|
||||
evaltab &tab,
|
||||
const room &room)
|
||||
{
|
||||
const auto &opts{*eval.opts};
|
||||
const event::prev prev{event};
|
||||
tab.prev_count = size(json::get<"prev_events"_>(prev));
|
||||
for(size_t i(0); i < tab.prev_count; ++i)
|
||||
{
|
||||
const auto &prev_id
|
||||
{
|
||||
prev.prev_event(i)
|
||||
};
|
||||
|
||||
if(m::exists(prev_id))
|
||||
{
|
||||
++tab.prev_exists;
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool can_fetch
|
||||
{
|
||||
opts.fetch_prev && bool(m::fetch::enable)
|
||||
};
|
||||
|
||||
const bool fetching
|
||||
{
|
||||
can_fetch && start(room.room_id, prev_id)
|
||||
};
|
||||
|
||||
tab.prev_fetching += fetching;
|
||||
}
|
||||
|
||||
assert(tab.prev_exists <= tab.prev_count);
|
||||
if(tab.prev_exists == tab.prev_count)
|
||||
return;
|
||||
|
||||
log::dwarning
|
||||
{
|
||||
log, "%s %s prev_events:%zu hit:%zu miss:%zu fetching:%zu",
|
||||
loghead(eval),
|
||||
at<"event_id"_>(event),
|
||||
tab.prev_count,
|
||||
tab.prev_exists,
|
||||
tab.prev_count - tab.prev_exists,
|
||||
tab.prev_fetching,
|
||||
};
|
||||
|
||||
const bool &prev_wait{opts.fetch_prev_wait};
|
||||
if(prev_wait && tab.prev_fetching) for(size_t i(0); i < tab.prev_count; ++i)
|
||||
{
|
||||
const auto &prev_id
|
||||
{
|
||||
prev.prev_event(i)
|
||||
};
|
||||
|
||||
dock.wait([&prev_id]
|
||||
{
|
||||
return !requests.count(prev_id);
|
||||
});
|
||||
|
||||
tab.prev_fetched += m::exists(prev_id);
|
||||
}
|
||||
|
||||
const bool &prev_any{opts.fetch_prev_any};
|
||||
if(prev_any && tab.prev_exists + tab.prev_fetched == 0)
|
||||
throw vm::error
|
||||
{
|
||||
vm::fault::EVENT, "Failed to fetch any prev_events for %s in %s",
|
||||
json::get<"event_id"_>(event),
|
||||
json::get<"room_id"_>(event)
|
||||
};
|
||||
|
||||
const bool &prev_all{opts.fetch_prev_all};
|
||||
if(prev_all && tab.prev_exists + tab.prev_fetched < tab.prev_count)
|
||||
throw vm::error
|
||||
{
|
||||
vm::fault::EVENT, "Failed to fetch all %zu required prev_events for %s in %s",
|
||||
tab.prev_count,
|
||||
json::get<"event_id"_>(event),
|
||||
json::get<"room_id"_>(event)
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/fetch.h
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
namespace ircd::m::fetch
|
||||
{
|
||||
struct request; // m/fetch.h
|
||||
struct evaltab;
|
||||
|
||||
static bool operator<(const request &a, const request &b) noexcept;
|
||||
static bool operator<(const request &a, const string_view &b) noexcept;
|
||||
|
@ -46,12 +47,24 @@ namespace ircd::m::fetch
|
|||
static size_t request_cleanup();
|
||||
static void request_worker();
|
||||
|
||||
static void hook_handler(const event &, vm::eval &);
|
||||
static void hook_handle_prev(const event &, vm::eval &, evaltab &, const room &);
|
||||
static void hook_handle_auth(const event &, vm::eval &, evaltab &, const room &);
|
||||
static void hook_handle(const event &, vm::eval &);
|
||||
|
||||
static void init();
|
||||
static void fini();
|
||||
}
|
||||
|
||||
struct ircd::m::fetch::evaltab
|
||||
{
|
||||
size_t auth_count {0};
|
||||
size_t auth_exists {0};
|
||||
size_t prev_count {0};
|
||||
size_t prev_exists {0};
|
||||
size_t prev_fetching {0};
|
||||
size_t prev_fetched {0};
|
||||
};
|
||||
|
||||
template<class... args>
|
||||
bool
|
||||
ircd::m::fetch::submit(const m::event::id &event_id,
|
||||
|
|
Loading…
Reference in a new issue