Example #1
0
    def error(self, action: str, params: object, result: Result) -> bool:
        """
        Add an error entry to the database

        Parameters
        ----------
        action : str
            A unique identifier for the action, usually ${method_name}:${class name}
        params : object
            The arguments to the method as scalar, list or dict
        result: metaroot.api.Result
            The Result of the failed operation that contains more granular information about the error

        Returns
        ---------
        metaroot.api.Result
            True for success

        Raises
        ---------
        Exception
            if the database if an underlying operation raised an exception
        """
        return self._insert(
            (datetime.datetime.now(), ActivityStream.ERROR, action,
             yaml.safe_dump(params), result.status,
             yaml.safe_dump(result.to_transport_format())))
Example #2
0
    def _safe_call(self,
                   method_name: str,
                   args: list,
                   target_managers="any") -> Result:
        """
        Iterates over the list of Managers, calling manager methods that implement the API request and returning the
        individual and overall result.

        Parameters
        ----------
        method_name: str
            The name of the method that should be called on each Manager
        args: list
            An ordered list of arguments that match the method signature
        target_managers: object
            Either the string "any" meaning all managers that implement the method will be called, or a list of
            manager class names that should be called

        Returns
        -------
        Result
            Result.status is the overall status: 0 for success, >0 for error
            Result.response is a dictionary with keys that are the class names of each Manager that implements the
            requested method and the value of each key is the specific Result returned by the call to that Manger
            class method
        """
        status = 0
        all_results = {}

        # If operating in read-only mode, refuse all write requests
        if self._read_only:
            if "add" in method_name or "delete" in method_name or "associate" in method_name or \
               "update" in method_name or "set" in method_name:
                result = Result(
                    470,
                    "Read-only operation is enabled, but write operation requested"
                )
                self.__activity_stream.record(method_name + ":any", args,
                                              result)
                return result

        n_priors = 0
        for manager in self._managers:
            # Filter which mangers to target (by default all will be targeted)
            if target_managers == "any" or manager.__class__.__name__ in target_managers:

                # Find the method on the manager (skip if not defined)
                try:
                    method = getattr(manager, method_name)
                except AttributeError as e:
                    self._logger.debug(
                        "Method %s is not defined for manager/hook %s",
                        method_name, manager.__class__.__name__)
                    continue

                result = method(*args)
                status = status + result.status
                all_results[
                    manager.__class__.__name__] = result.to_transport_format()
                self.__activity_stream.record(
                    method_name + ":" + manager.__class__.__name__, args,
                    result)

                # Allow reactions to occur in response to result of last action
                n_priors = n_priors + self._reactions.occur_in_response_to(
                    manager.__class__.__name__, method_name, args, result,
                    n_priors)

        return Result(status, all_results)