0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-05-29 00:03:45 +02:00

ircd:Ⓜ️:vm::fetch: Add vm::opts and conf items for prev fetch wait backoff.

This commit is contained in:
Jason Volk 2020-04-17 14:01:58 -07:00
parent df29c95dad
commit de8f32e86a
2 changed files with 74 additions and 10 deletions

View file

@ -282,6 +282,20 @@ struct ircd::m::vm::opts
/// corollary conditions are similar to fetch_prev_any.
bool fetch_prev_all {false};
/// The number of iterations of the wait cycle which checks for missing
/// prev_events will iterate before issuing remote fetches for them.
/// The default is 0 which bypasses the functionality, and is recommended
/// when the evaluator is confident missing prev_events won't arrive
/// elsehow. Setting to -1 enables it with an auto/conf value.
size_t fetch_prev_wait_count {0};
/// Base time to wait for missing prev_events to arrive at the server by
/// some other means before issuing remote fetches for them. The waiting
/// occurs in a loop where prev_events satisfaction is checked at each
/// iteration. This value is multiplied by the number of iterations for
/// multiplicative backoff. The default of -1 is auto / conf.
milliseconds fetch_prev_wait_time {-1};
/// The limit on the number of events to backfill if any of the prev_events
/// are missing. -1 is auto / conf.
size_t fetch_prev_limit = -1;

View file

@ -11,6 +11,7 @@
namespace ircd::m::vm::fetch
{
static void prev_check(const event &, vm::eval &);
static bool prev_wait(const event &, vm::eval &);
static std::forward_list<ctx::future<m::fetch::result>> prev_fetch(const event &, vm::eval &, const room &);
static void prev(const event &, vm::eval &, const room &);
static std::forward_list<ctx::future<m::fetch::result>> state_fetch(const event &, vm::eval &, const room &);
@ -20,6 +21,8 @@ namespace ircd::m::vm::fetch
static void auth(const event &, vm::eval &, const room &);
static void handle(const event &, vm::eval &);
extern conf::item<milliseconds> prev_wait_time;
extern conf::item<size_t> prev_wait_count;
extern conf::item<size_t> prev_backfill_limit;
extern conf::item<seconds> event_timeout;
extern conf::item<seconds> state_timeout;
@ -85,6 +88,20 @@ ircd::m::vm::fetch::prev_backfill_limit
{ "default", 128L },
};
decltype(ircd::m::vm::fetch::prev_wait_count)
ircd::m::vm::fetch::prev_wait_count
{
{ "name", "ircd.m.vm.fetch.prev.wait.count" },
{ "default", 4L },
};
decltype(ircd::m::vm::fetch::prev_wait_time)
ircd::m::vm::fetch::prev_wait_time
{
{ "name", "ircd.m.vm.fetch.prev.wait.time" },
{ "default", 200L },
};
//
// fetch_phase
//
@ -560,23 +577,19 @@ ircd::m::vm::fetch::prev(const event &event,
prev.prev_events_count()
};
size_t prev_exists
const size_t prev_exists
{
prev.prev_events_exist()
};
//TODO: remove or soften when eval::count() / eval::find_pdu()
//TODO: is restored kthx (though it can never truly be removed)
for(size_t check(0); prev_exists < prev_count && check < 3;)
{
ctx::sleep(milliseconds(++check * 333));
prev_exists = prev.prev_events_exist();
}
assert(prev_exists <= prev_count);
if(prev_count == prev_exists)
return;
// Attempt to wait for missing prev_events without issuing fetches here.
if(prev_wait(event, eval))
return;
if(!opts.fetch_prev || !m::vm::fetch::enable)
{
prev_check(event, eval);
@ -620,7 +633,7 @@ ircd::m::vm::fetch::prev(const event &event,
break;
// Check for satisfaction.
if((prev_exists = prev.prev_events_exist()) == prev_count)
if(prev.prev_events_exist() == prev_count)
return;
}
@ -754,6 +767,43 @@ ircd::m::vm::fetch::prev_fetch(const event &event,
return ret;
}
//TODO: Adjust when PDU lookahead/lookaround is fixed in the vm::eval iface.
//TODO: Wait on another eval completion instead of just coarse sleep()'s.
bool
ircd::m::vm::fetch::prev_wait(const event &event,
vm::eval &eval)
{
const auto &opts(*eval.opts);
const event::prev prev(event);
const size_t prev_count
{
prev.prev_events_count()
};
const size_t &wait_count
{
ssize_t(opts.fetch_prev_wait_count) >= 0?
opts.fetch_prev_wait_count:
size_t(prev_wait_count)
};
const milliseconds &wait_time
{
opts.fetch_prev_wait_time >= 0ms?
opts.fetch_prev_wait_time:
milliseconds(prev_wait_time)
};
size_t i(0); while(i < wait_count)
{
sleep(milliseconds(++i * wait_time));
if(prev_count == prev.prev_events_exist())
return true;
}
return false;
}
void
ircd::m::vm::fetch::prev_check(const event &event,
vm::eval &eval)