From 02b835eb2bb524887e75c2cd73850a9917870ea2 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 18 Apr 2019 21:23:00 -0700 Subject: [PATCH] ircd::m::feds: Add additional options; document options. --- include/ircd/m/feds.h | 30 +++++++++++++++++++++++++++++ modules/s_feds.cc | 45 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/include/ircd/m/feds.h b/include/ircd/m/feds.h index 8311bc1f6..ceb5bd946 100644 --- a/include/ircd/m/feds.h +++ b/include/ircd/m/feds.h @@ -50,13 +50,43 @@ struct ircd::m::feds::result struct ircd::m::feds::opts { + /// Operation type enum op op {(enum op)0}; + + /// Timeout for this operation. For a batch of operations, this system + /// may attempt -- but does not guarantee -- to cancel timed-out requests + /// before the highest timeout value in the batch. milliseconds timeout {20000L}; + + /// Apropos room_id: this is almost always required for this interface + /// because the servers in the room is used for the request target set. m::room::id room_id; + + /// Apropos event_id for several operations. m::event::id event_id; + + /// Apropos user_id for several operations. m::user::id user_id; + + /// Misc string argument registers. These convey values for special + /// features in individual operations. string_view arg[4]; // misc argv + + /// Misc integer argument registers. These convey values for special + /// features in individual operations. uint64_t argi[4]; // misc integer argv + + /// Whether exceptions from the supplied result closure are propagated. + bool nothrow_closure {false}; + + /// When nothrow_closure is true, this determines whether or not to + /// continue receiving results or to break and return. True to continue. + bool nothrow_closure_retval {true}; + + /// Whether to call the user's result closure for error results, which + /// would have the eptr set. When this is false, the closure is never + /// invoked with eptr set and nothrow_closure_retval is used to continue. + bool closure_errors {true}; }; enum class ircd::m::feds::op diff --git a/modules/s_feds.cc b/modules/s_feds.cc index d0a6a1824..5b9ad0ec6 100644 --- a/modules/s_feds.cc +++ b/modules/s_feds.cc @@ -24,6 +24,8 @@ namespace ircd::m::feds template using create_closure = std::function &, const string_view &origin)>; template static request_list creator(const opts &, const create_closure &); + + static bool call_user(const closure &closure, const result &result); static bool handler(request_list &, const milliseconds &, const closure &); static request_list head(const opts &, const closure &); @@ -351,6 +353,10 @@ ircd::m::feds::handler(request_list &reqs, }; assert(it != end(reqs)); + const unwind remove{[&reqs, &it] + { + reqs.erase(it); + }}; request_base &req(**it); server::request &sreq(dynamic_cast(req)); try @@ -358,23 +364,54 @@ ircd::m::feds::handler(request_list &reqs, const auto code{sreq.get()}; const json::array &array{sreq.in.content}; const json::object &object{sreq.in.content}; - if(!closure({req.opts, req.origin, {}, object, array})) + const result result + { + req.opts, req.origin, {}, object, array + }; + + if(!call_user(closure, result)) return false; } catch(const std::exception &) { + if(!req.opts->closure_errors && !req.opts->nothrow_closure_retval) + return false; + + if(!req.opts->closure_errors) + continue; + const ctx::exception_handler eptr; const std::exception_ptr &eptr_(eptr); - if(!closure({req.opts, req.origin, eptr_})) + const result result + { + req.opts, req.origin, eptr_ + }; + + if(!call_user(closure, result)) return false; } - - reqs.erase(it); } return true; } +bool +ircd::m::feds::call_user(const closure &closure, + const result &result) +try +{ + return closure(result); +} +catch(const std::exception &) +{ + assert(result.request); + if(result.request->nothrow_closure) + return result.request->nothrow_closure_retval; + + throw; +} + + template ircd::m::feds::request_list ircd::m::feds::creator(const opts &opts,