Don't take lock for read/GET operations

This commit is contained in:
Alexandre Aubin 2022-12-24 00:02:24 +01:00
parent 80873777c6
commit 676a19dc28
3 changed files with 36 additions and 19 deletions

View file

@ -515,6 +515,8 @@ class ActionsMap:
tid = arguments.pop("_tid") tid = arguments.pop("_tid")
arguments = self.extraparser.parse_args(tid, arguments) arguments = self.extraparser.parse_args(tid, arguments)
want_to_take_lock = self.parser.want_to_take_lock(args, **kwargs)
# Retrieve action information # Retrieve action information
if len(tid) == 4: if len(tid) == 4:
namespace, category, subcategory, action = tid namespace, category, subcategory, action = tid
@ -537,7 +539,7 @@ class ActionsMap:
full_action_name = "{}.{}.{}".format(namespace, category, action) full_action_name = "{}.{}.{}".format(namespace, category, action)
# Lock the moulinette for the namespace # Lock the moulinette for the namespace
with MoulinetteLock(namespace, timeout, self.enable_lock): with MoulinetteLock(namespace, timeout, self.enable_lock and want_to_take_lock):
start = time() start = time()
try: try:
mod = __import__( mod = __import__(
@ -662,6 +664,13 @@ class ActionsMap:
if interface_type in authentication: if interface_type in authentication:
action_parser.authentication = authentication[interface_type] action_parser.authentication = authentication[interface_type]
# Disable the locking mechanism for all actions that are 'GET' actions on the api
routes = action_options.get("api")
if routes and isinstance(routes, str) and routes.startswith("GET "):
action_parser.want_to_take_lock = False
else:
action_parser.want_to_take_lock = True
# subcategory_name is like "cert" in "domain cert status" # subcategory_name is like "cert" in "domain cert status"
# subcategory_values is the values of this subcategory (like actions) # subcategory_values is the values of this subcategory (like actions)
for subcategory_name, subcategory_values in subcategories.items(): for subcategory_name, subcategory_values in subcategories.items():
@ -705,5 +714,12 @@ class ActionsMap:
if interface_type in authentication: if interface_type in authentication:
action_parser.authentication = authentication[interface_type] action_parser.authentication = authentication[interface_type]
# Disable the locking mechanism for all actions that are 'GET' actions on the api
routes = action_options.get("api")
if routes and isinstance(routes, str) and routes.startswith("GET "):
action_parser.want_to_take_lock = False
else:
action_parser.want_to_take_lock = True
logger.debug("building parser took %.3fs", time() - start) logger.debug("building parser took %.3fs", time() - start)
return top_parser return top_parser

View file

@ -647,6 +647,12 @@ class ActionsMapParser(BaseActionsMapParser):
return parser.authentication return parser.authentication
def want_to_take_lock(self, _, route):
_, parser = self._parsers[route]
return getattr(parser, "want_to_take_lock", True)
def parse_args(self, args, **kwargs): def parse_args(self, args, **kwargs):
"""Parse arguments """Parse arguments

View file

@ -387,25 +387,9 @@ class ActionsMapParser(BaseActionsMapParser):
) )
def auth_method(self, args): def auth_method(self, args):
# FIXME? idk .. this try/except is duplicated from parse_args below
# Just to be able to obtain the tid
try:
ret = self._parser.parse_args(args)
except SystemExit:
raise
except Exception as e:
error_message = "unable to parse arguments '{}' because: {}".format(
" ".join(args),
e,
)
logger.exception(error_message)
raise MoulinetteValidationError(error_message, raw_msg=True)
tid = getattr(ret, "_tid", None) ret = self.parse_args(args)
tid = getattr(ret, "_tid", [])
# Ugh that's for yunohost --version ...
if tid is None:
return None
# We go down in the subparser tree until we find the leaf # We go down in the subparser tree until we find the leaf
# corresponding to the tid with a defined authentication # corresponding to the tid with a defined authentication
@ -433,6 +417,17 @@ class ActionsMapParser(BaseActionsMapParser):
logger.exception(error_message) logger.exception(error_message)
raise MoulinetteValidationError(error_message, raw_msg=True) raise MoulinetteValidationError(error_message, raw_msg=True)
def want_to_take_lock(self, args):
ret = self.parse_args(args)
tid = getattr(ret, "_tid", [])
if len(tid) == 3:
_p = self._subparsers.choices[tid[1]]._actions[1].choices[tid[2]]
elif len(tid) == 4:
_p = self._subparsers.choices[tid[1]]._actions[1].choices[tid[2]]._actions[1].choices[tid[3]]
return getattr(_p, "want_to_take_lock", True)
class Interface: class Interface: