GithubHelp home page GithubHelp logo

Comments (7)

alanking avatar alanking commented on June 28, 2024

CAT_NO_ROWS_FOUND and CAT_SUCCESS_BUT_WITH_NO_INFO appear to be singled out in the error handling for running a rule:

const auto error_occurred = !err.ok() &&
err.code() != CAT_NO_ROWS_FOUND &&
err.code() != CAT_SUCCESS_BUT_WITH_NO_INFO;

Even though I was the last one to touch that line, the error handling for the effect_handler was added in this commit: 33dcf82 These two error codes were always singled out, unfortunately without explanation or a linked issue. Throughout the iRODS server, these are often (though not always) considered to be error codes that do not necessarily indicate failure, which is probably why this was done.

Any ideas, @trel, @d-w-moore?

from irods_rule_engine_plugin_python.

trel avatar trel commented on June 28, 2024

Alan's diagnosis is correct - these error codes are sometimes used just to communicate back to the caller that the query succeeded in its execution, but didn't return any results.

Is there another appropriate code you can use to signal the error you want from your rule?
See https://github.com/irods/irods/blob/4-2-stable/lib/core/include/rodsErrorTable.h

from irods_rule_engine_plugin_python.

d-w-moore avatar d-w-moore commented on June 28, 2024

@deanlinssen The purpose of msiExit microservice seems to be mainly to add the specified message to the RError stack for the benefit of any client that might check for such a message. In the native rule engine plugin (NREP), calling it definitely also causes a rule to unconditionally stop execution at the point of the microservice call.

However, as @alanking pointed out,-808000 (CAT_NO_ROWS_FOUND)and-819000 ( CAT_SUCCESS_BUT_WITH_NO_INFO)are the two error codes that the Python REP treats as special, i.e. as "non-fatal" error codes, if you like. CAT_NO_ROWS_FOUND was probably excepted expressly so that GenQuery results could be iterated to the end without aborting the calling rules; probably there was a similar purpose in mind for CAT_SUCCESS_BUT_WITH_NO_INFO.

There is hope, though. In the Python rule, you can simply use a return statement to abort rule execution early. So, something like the following code might serve your purpose well:

import re
from irods_errors import (CAT_SUCCESS_BUT_WITH_NO_INFO, #-819000
                          CAT_NO_ROWS_FOUND  # -808000
)
class FailRequest(Exception): pass

def fail_with_rerror_message(code, message ,callback):
    try:
        callback.msiExit(code,message)
    except RuntimeError as runerr:
        mt = re.search("\[iRods__Error__Code:(-?\d+)\]",runerr.message)
        if mt: raise FailRequest( int(mt.group(1)) )  # process fatal errors
    else:
        if int(code) in ( CAT_SUCCESS_BUT_WITH_NO_INFO,  # process non-fatal errors
                          CAT_NO_ROWS_FOUND,
        ): raise FailRequest( int(code) )

def python_rule(rule_args,callback,rei):

    error_code = rule_args[0]

    try:
        fail_with_rerror_message( error_code, "this goes to rerror stack for client", callback )
    except FailRequest: return

    callback.writeLine("serverLog","we won't get here if error_code spells out a negative integer")


Now... for demonstration purposes here, I've got Native REP and Python REP both enabled on my machine so that I can send parameters to the python rule. I can then do:

$ irule -r irods_rule_engine_plugin-irods_rule_language-instance 'python_rule("-808000")' null null
Level 0: this goes to rerror stack for client

And regardless of what negative code I send, nothing will print to the server's error log because of the return statement.

The above fail_with_rerror_message function might even be generalized to something that called a function by name with requested arguments

def rule_or_msvc_call_with_abort ( target_name, target_args, callback):
   try: getattr( callback, target_name ) (*target_args)
   except: ... # ( The rest is 
   else: ...     # unchanged )

from irods_rule_engine_plugin_python.

d-w-moore avatar d-w-moore commented on June 28, 2024

@deanlinssen - Also : To be consistent and play well with the rest of the Rule Engine framework, I suppose the next to last line in python_rule should fail properly instead of using just a barereturn (which just returns 0, a success code):

    except FailRequest as exc:
        return exc.args[0]

Still, I daresay you got a good sense from the above post of what was going on. So really: return error_code is equivalent to a call to the native microservice fail(error_code)if error_code is negative, or to the succeed microservice if it is zero.

from irods_rule_engine_plugin_python.

deanlinssen avatar deanlinssen commented on June 28, 2024

@d-w-moore @trel @alanking Thank you guys for your prompt reactions and clear diagnoses. We now have a much more clear understanding of what is going on here.

Off topic: What I still do not understand though, is why "-808000", "-808001", "-808002" etc. all return the same CAT_NO_ROWS_FOUND exception

from irods_rule_engine_plugin_python.

trel avatar trel commented on June 28, 2024

Excellent.

In iRODS... the thousands number is the iRODS Error, and the last three digits are the underlying errno.

From top of https://github.com/irods/irods/blob/4-2-stable/lib/core/include/rodsErrorTable.h:

/**
 * @defgroup error_codes iRODS ERROR Codes
 * @note ERROR code format:
 *
 *      -mmmmnnn
 *
 * Example:    SYS_SOCK_OPEN_ERR -1000
 *
 * Where -mmmm000 is an iRODS ERROR Code
 *
 * This error (-1000) is the error that occurs when a
 * socket open call failed. Here mmmm = 1.
 *
 * nnn is the errno associated with the socket open call.
 *
 * If the errno is 34, then the error returned to the user
 * is -1034. iRODS uses 3 digits for nnn because the errno
 * is less than 1000.
 *
 */

from irods_rule_engine_plugin_python.

d-w-moore avatar d-w-moore commented on June 28, 2024

Regarding the rounding of 1000's when an errno offset is present --
One could do something like (referring to the code I posted above):

round_code = lambda err: ((err-1)//1000+1)*1000 if err<=-1000 else err
#...
    if rounded_code(int(code)) in ( CAT_SUCCESS_BUT_WITH_NO_INFO,  # process non-fatal errors
                                    CAT_NO_ROWS_FOUND,   ):
         raise FailRequest( int(code) )
#...

from irods_rule_engine_plugin_python.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.