diff --git a/matrix/sync.cc b/matrix/sync.cc index 507ea2352..d3da3a1c7 100644 --- a/matrix/sync.cc +++ b/matrix/sync.cc @@ -135,13 +135,26 @@ ircd::m::sync::make_since(const mutable_buffer &buf, const int64_t &val, const string_view &flags) { - return fmt::sprintf + const string_view &prefix + { + val? + "ctor_"_sv: + ""_sv + }; + + const string_view &snapshot { - buf, "ctor_%lu%s%s", - val, flags? "_0_"_sv: - flags, + flags + }; + + return fmt::sprintf + { + buf, "%s%lu%s%s", + prefix, + val, + snapshot, flags, }; } diff --git a/modules/client/sync.cc b/modules/client/sync.cc index 9e5fb0840..5c5c2e15a 100644 --- a/modules/client/sync.cc +++ b/modules/client/sync.cc @@ -14,7 +14,7 @@ namespace ircd::m::sync struct response; static const_buffer flush(data &, resource::response::chunked &, const const_buffer &); - static void empty_response(data &, const uint64_t &next_batch); + static bool empty_response(data &, const uint64_t &next_batch); static bool linear_handle(data &); static bool polylog_handle(data &); static bool longpoll_handle(data &); @@ -27,6 +27,7 @@ namespace ircd::m::sync extern conf::item longpoll_enable; extern conf::item polylog_phased; extern conf::item polylog_only; + extern conf::item MSC2855; extern resource::method method_get; extern const string_view description; @@ -150,6 +151,13 @@ ircd::m::sync::longpoll_enable { "default", true }, }; +decltype(ircd::m::sync::MSC2855) +ircd::m::sync::MSC2855 +{ + { "name", "ircd.client.sync.MSC2855.enable" }, + { "default", true }, +}; + // // GET sync // @@ -202,15 +210,20 @@ ircd::m::sync::handle_get(client &client, // event which doesn't exist yet. There is no reason for the since parameter // to be greater than that, unless it's a negative integer and phased // sync is enabled - if(!polylog_phased || !phased_range) - if(range.first > range.second) - throw m::NOT_FOUND - { - "Since parameter '%lu' is too far in the future." - " Cannot be greater than '%lu'.", - range.first, - range.second - }; + const bool invalid_since + { + (!polylog_phased || !phased_range) + && (range.first > range.second) + }; + + if(unlikely(invalid_since && !MSC2855)) + throw m::NOT_FOUND + { + "Since parameter '%lu' is too far in the future." + " Cannot be greater than '%lu'.", + range.first, + range.second + }; // Query and cache the device ID for the access token of this request on // the stack here for this sync. @@ -346,36 +359,38 @@ ircd::m::sync::handle_get(client &client, // The return value from the operation will be false if no output was // generated by the sync operation, indicating we should finally send an // empty response. - const bool complete + bool complete { - should_linear? - linear_handle(data): - - should_polylog? - polylog_handle(data): - false + || invalid_since }; - if(complete) - return std::move(response); + if(!complete && should_polylog) + complete = polylog_handle(data); - if(longpoll_handle(data)) - return std::move(response); + if(!complete && should_linear) + complete = linear_handle(data); - const auto &next_batch - { - polylog_only? - data.range.first: + if(!complete) + complete = longpoll_handle(data); - data.range.second - }; + if(!complete || invalid_since) + complete = empty_response(data, uint64_t + { + invalid_since? + 0UL: - empty_response(data, next_batch); + polylog_only? + data.range.first: + + data.range.second + }); + + assert(complete); return std::move(response); } -void +bool ircd::m::sync::empty_response(data &data, const uint64_t &next_batch) { @@ -404,12 +419,30 @@ ircd::m::sync::empty_response(data &data, } }; - log::debug + const auto &reason { - log, "request %s timeout @%lu", - loghead(data), - next_batch + next_batch? + "timeout"_sv: + "MSC2855 clear cache & reload"_sv }; + + const auto &level + { + next_batch? + log::DEBUG: + log::WARNING + }; + + log::logf + { + log, level, + "request %s %s @%lu", + loghead(data), + reason, + next_batch, + }; + + return true; } ircd::const_buffer