Qorus FAQs

Installation FAQs

I Have Just Enabled RBAC and Set the rbac-force-user Option, Why Can't I Start the System? (Enterprise Edition Only)

A typical rbac-force-user option setting in the options file could be as follows:

qorus.rbac-force-user: localhost=admin

Which could result in an error as follows if the admin user doesn't exist in the system:

RBAC-OVERRIDE-ERROR: User exception: RBAC.qc:996: RBAC-OVERRIDE-ERROR: cannot override source "localhost" to user "admin"; user does not exist
call stack:
  RBAC::addOverrideIntern() called at RBAC.qc:979 (user function)
  RBAC::init() called at qorus.q:367 (user function)

In this case, you need to create the admin user before the system can be started.
To do this offline, use the user-tool script to create the user offline as follows:

user-tool -Aadmin:password:superuser:Administrator

Note:

  • The Community Edition of Qorus does not support users or permissions; this question only applies to the Enterprise Edition of Qorus
  • To create a user when the system is running, use qrest with the POST /api/latest/users API as in the following example:
    qrest post users username=admin,pass=password,roles=superuser,name=Administrator

Operational FAQs

How Can I See Which Objects Are in the Database from the Command Line?

Use oload to list objects with the -L object option as follows:

List Workflows

oload -Lw

List Services

oload -Ls

List Jobs

oload -Lj

List Mappers

oload -Lm

List Classes

oload -Lc

Notes:

  • These commands can be executed even when the server is down because they use direct database access.
  • Execute oload -h for a complete list of objects that can be listed

How Can I Set Config Item Values from the Command Line?

Use qrest to set config item values as in the following examples:

Set Config Item Values on a Workflow Step

qrest put workflows/WORKFLOW-NAME/stepinfo/StepName/config/config-item-name "value={opt1=value,opt2=value}"

Set Config Item Values on a Service

qrest put services/service-name/config/config-item-name "value={opt1=value,opt2=value}"

Set Config Item Values on a Job

qrest put jobs/job-name/config/config-item-name "value={opt1=value,opt2=value}"

Notes:

  • The APIs called by qrest in the above examples use parse_to_qore_value() to parse command-line arguments used as the message body.

How Can I Set Workflow / Service / Job Options from the Command Line?

Use qrest to set interface options as in the following examples:

Set Workflow Options

qrest put workflows/WORKFLOW-NAME.setOptions "options={opt1=value,opt2=value}"

Set Service Options

qrest put services/service-name/setOptions "options={opt1=value,opt2=value}"

Set Job Options

qrest put jobs/job-name/setOptions "options={opt1=value,opt2=value}"

Notes:

  • The APIs called by qrest in the above examples use parse_to_qore_value() to parse command-line arguments used as the message body.

How Can I Update a Connection From the Command Line?

See the following example for updating a connection option:

qrest put connections/connection-name options='{keyfile=path_to_key}'

How Can I See a Call Stack of Interface Execution in Realtime?

Use qctl to display a list of all thread call stacks with the threads option as in the following example:

qctl threads <process-name>

Note: Each line in each Qorus log file shows the thread ID in the field immediately following the date and time; in the following example T793 gives TID 793

2016.08.31 11:01:39.580030 T793: ID 142: WI 167261: mip96_it_finalize(1078/0): step completed with status "C" (COMPLETE)

Why Can't I Stop My Interface?

If you are stopping your workflow, service, or job manually, the system will start it again automatically if all its dependencies are available and the manage-interfaces option is enabled and the interface is eligible for autostarting.

To be eligible for autostarting, a workflow must have a positive autostart value; a service must have its autostart values enabled, and a job must be active.

Instead of stopping a workflow or unloading a job, workflows, services, and jobs should be disabled. See the next question for more information on how to disable interfaces.

How Do I Disable an Interface from the Command Line?

Use qrest as follows:

Disable a Workflow

qrest put workflows/WORKFLOW-NAME/disable

Disable a Service

qrest put services/service-name/disable

Disable a Job

qrest put jobs/job-name/disable

How Do I Enable a Disabled Interface?

Use qrest to enable a disabled interface as follows:

Enable a Workflow

qrest put workflows/WORKFLOW-NAME/enable

Enable a Service

qrest put services/service-name/enable

Enable a Job

qrest put jobs/job-name/enable

How Are Arguments Specified on the Command Line?

Command-line arguments (with qrest, oprop, and ocmd, for example) are parsed on the client side before sending to the server with QorusClientApi::parseToQoreValue().

To send a list of values, write the values separated by commas as follows:

1, "2", three, 4

To include a hash, write it in key=value format surrounded by curly brackets and separated by commas:

1, "2", three, 4, {key1 = value1, key2 = value2}

To send a raw string without any format parsing, prepend %STR= to the string as follows:

%STR=1, "2", three, 4, {key1 = value1, key2 = value2}

It's also possible to send an expression to be evaluated on the server side by prepending %EVAL= as follows:

%EVAL={"key": get_qore_library_info()}

How Can I Restart the System Remotely?

For Qorus in a Docker Container or in Kubernetes

The recommended way to restart Qorus in Docker is to execute docker restart <qorus-container-name>, in Kubernetes is to recreate the qorus-core deployment, otherwise a brute-force way to restart Qorus in Docker or Kubernetes it to kill the qorus-core process.

This can be performed with the UI by killing the process in the cluster page (System -> Cluster); click on the red x icon next to the qorus-core process to kill it.

qorus-master will restart qorus-core automatically in this case.

Qorus Cluster Page

For Non-Container-Based Installations

Use qrest to call the PUT /api/latestsystem/restart API as in the following example:

qrest put system/restart

Notes:

  • The calling user must have the SHUTDOWN permission to execute this API.
  • The PUT /api/system/restart API uses a default two-minute timeout for restarting the system; if the system does not shut down within the timeout period, then the Qorus process is killed and immediately restarted; see the documentation in the previous links for information about how to send a different timeout option if necessary (for example your Qorus system needs more time to perform an orderly shutdown due to the nature of the interfaces running on it).
  • Do not use this API in Docker or Kubernetes instances, as it can cause problems

How Can I Rotate Log Files Manually?

Use qrest to call the PUT /api/system/rotateLogFiles API as in the following example:

qrest put system/rotateLogFiles

Note that log file rotation can be enabled automatically using the qorus-log-rotator job; this as well as system schema archiving can be enabled by running schema-tool -m in Qorus 6.0 or later.

See also:

How Can I Update an External Connection With the Command Line?

You can update it in the system using qrest and the PUT /api/latest/connections/name/update REST API as follows:

qrest put connections/connection-name/update url=ftp://example.com

How Are Arguments Specified in the UI?

Arguments when sent from the UI are specified as strings and parsed server-side with parse_to_qore_value().

To send a list of values, write the values separated by commas as follows:

1, "2", three, 4

To include a hash, write it in key=value format surrounded by curly brackets and separated by commas:

1, "2", three, 4, {key1 = value1, key2 = value2}

To send a raw string without any format parsing, prepend %STR= to the string as follows:

%STR=1, "2", three, 4, {key1 = value1, key2 = value2}

It's also possible to send an expression to be evaluated on the server side by prepending %EVAL= as follows:

%EVAL={"key": get_qore_library_info()}

Docker and Kubernetes FAQs

How Can I Execute Qorus Command-Line Commands in a Container?

From Docker:

docker exec qorus bash -l -c "qrest system/pid"

From Kubernetes:

kubectl exec deploy/qorus-core -- bash -l -c "qrest system/pid"

How Can I Install Python Modules For Use With Qorus in Docker?

Use pip in the container to install the modules in /opt/qorus/user/python, the standard location and persistent directory for Python modules in Qorus:

docker exec qorus bash -l -c "pip install --prefix=/opt/qorus/user/python <python-module-name>"

How Can I Install Python Modules For Use With Qorus in Kubernetes?

Use pip in any Qorus pod to install the modules in /opt/qorus/user/python, the standard location and persistent directory shared in all pods for Python modules in Qorus:

kubectl exec deploy/qorus-core -- bash -l -c "pip install --prefix=/opt/qorus/user/python <python-module-name>"

Where Can I Find More Information About Qorus in Docker?

See the qorus-docker project on GitHub.

Qorus images are available here: https://gallery.ecr.aws/qorus. qorus-ee images are for the Enterprise Edition, qorus-ce images are for the Community Edition.

Where Can I Find More Information About Qorus in Kubernetes?

See the qorus-kubernetes project on GitHub.

Developer FAQs

How can I see the source of objects from the command-line?

If the Qorus server is running, then you can use oview to dump the source code to objects from REST APIs as in the following examples:

Dump a Function's Source Code

oview func:function_name:1.0

Dump a Class's Source Code

oview class:ClassName:1.0

Dump a Service's Source Code

oview svc:service-name:1.0

Dump a Job's Source Code

oview job:job-name:1.0

More objects can be dumped; type oview -h for runtime help or check the oview documentation for more information.

Note: ojview can also dump job source code with ojview -f

How to add or update Qorus objects

Use oload utility with flags to refresh cache

# Qorus 3.1+
  oload -Rlv <files>
  # Qorus 3.0+
  oload -lvra <files>

Can I delete objects from the system?

Use the IDE

The Qorus IDE can be used to delete interfaces in a connected instance. Navigate to the Delete Interaces page and select the objects to be deleted.

Delete Interfaces

Use oload

oload can be used to delete interfaces as well as code and configuration objects in the database.

When deleting workflows, services, and jobs, ensure that the interface is not active by disabling the interface with qrest, then use the appropriate oload -X option delete the interface as in the following examples:

Delete a Workflow

oload -vR -Xworkflow:WORKFLOW-NAME:1.0

Delete a Service

oload -vR -Xservice:service-name:1.0

Delete a Job

oload -vR -Xjob:job-name:1.0

More objects can be deleted; type oload -h for runtime help or check the oload documentation for more information.

Notes:

  • The examples above use the -vR options to show more output and to also notify any running server that the given objects have been deleted

Why can't my workflow / service / job / mapper see the changes I just made to a DB table?

SqlUtil-based interfaces and system mappers use the Qorus SQL Object Cache in order to share SQL resource and provide high-performance access to static SQL configuration.

When interfaces and SqlUtil-based system mappers (i.e. any mapper using a DB table as an input or output data provider, for example) will retrieve the table definition from the cache to eliminate the acquisition and creation cost of the underlying AbstractTable objects.

When the tables change in the DB, the cached definitions need to be cleared so the new definition can be used in Qorus.

Clear SQL Cache Entries With the UI

Navigate to System -> Cache and clear the cached entries by clicking on the Clear button next to the entries you want to clear.

Clear SQL Cache With the Command Line

To clear the entire SQL cache with the command line, see the following example:

qrest put system/sqlcache/clear

Note: The above example clears the entire system SQL cache; see PUT /api/system/sqlcache/clear for more information about how objects for specific datasources and/or tables can be cleared.

I just deleted an interface with oload, but it's still visible in the UI, what's wrong?

You have to use the oload -R option to refresh the server after creating or deleting interfaces; to refresh the server by hand after deleting from the database, try one of the following commands:

After Deleting a Workflow

qrest put system/metadata/reload workflows=id
qrest put system/rbac/reload

After Deleting a Service

qrest put system/metadata/reload services=id
qrest put system/rbac/reload

After Deleting a Job

qrest put system/metadata/reload jobs=id
qrest put system/rbac/reload

Notes: Make sure and substitute id with the actual interface ID that was deleted.

Type oload -h for runtime help or check the oload documentation for more information on oload and also refer to the REST API documentation.

What is the easiest way to get the current workflow_instanceid from workflow code?

The easiest way is to call WorkflowApi::getWfiid() as in the following example:

int wfiid = WorkflowApi::getWfiid();

Another way is to call WorkflowApi::getWorkflowInstanceData() as in the following example:

softint wfiid = WorkflowApi::getWorkflowInstanceData().workflow_instanceid;

See Also: WorkflowApi::parentWfiid()

How can I insert the same sequence values in multiple columns using a system mapper?

When using a Qorus mapper with a DB table as an output data provider, you can use the sequence_currval field option to specify that a sequence value should be inserted with the same value as in another field (i.e. another column must insert this sequence with the sequence option).

How can I cancel a workflow order from within the same workflow?

Sometimes you may have the requirement to cancel a workflow order if a certain error occurs or if a certain condition is detected.

Workflow orders cannot be canceled from within their own code, so this must be done outside the workflow. The best way to do this is with a service.

The following is some example code that will cancel the workflow order and leave a note why the order was canceled.

cancel-service-1.0.qsd.yaml:

# This is a generated file, don't edit!
type: service
name: cancel-order
desc: |-
    ## Order cancelation service

    Cancels workflow orders in a background thread
lang: qore
author:
  - Qore Technologies, s.r.o.
base-class-name: QorusService
class-name: CancelOrder
version: "1.0"
groups:
  - EXAMPLES
servicetype: USER
code: cancel-order-1.0.qsd
methods:
  - name: cancel
    desc: cancels a workflow order in a background thread
  - name: stop
    desc: Stops the service
  - name: ping
    desc: returns the string OK

cancel-service-1.0.qsd:

%new-style
%strict-args
%require-types
%enable-all-warnings

class CancelOrder inherits QorusService {
    private {
        # statuses where it's OK to cancel; we use a hash with boolean True values to simulate a set
        const CancelStatuses = {
            OMQ::StatError: True,
            OMQ::StatRetry: True,
            OMQ::StatAsyncWaiting: True,
            OMQ::StatEventWaiting: True,
        };

        # check every 200 ms
        const PollInterval = 200ms;
    }

    int cancel(softint wfiid, timeout to = 1m) {
        return startThread(doCancel(), wfiid, to);
    }

    stop() {
        # this method is necessary due to the startThread() call in the cancel method
        # noop; cancel actions will time out
    }

    string ping() {
        return "OK";
    }

    private waitForStatus(int wfiid, timeout to) {
        date now = now_us();

        hash<auto> h;
        while (True) {
            # info.getWorkflowStatus2() retrieves the status from the cache if possible,
            # so if the order is being processed, then there is no SQL I/O
            h = omqservice.system.info.getWorkflowStatus2(wfiid);
            if (CancelStatuses{h.workflowstatus}) {
                break;
            }

            if (h.workflowstatus == OMQ::StatComplete) {
                throw "STATUS-ERROR", sprintf("workflow instance ID %d has status %y; cannot cancel", wfiid,
                    h.workflowstatus);
            }

            # wait for status to change
            # NOTE: this function call can throw an exception if the system is being shut down;
            #       it's not legal to sleep when a shutdown is in progress
            usleep(PollInterval);

            if ((now_us() - now) >= to) {
                throw "CANCEL-TIMEOUT", sprintf("cannot cancel workflow_instanceid %d (%s v%s workflowid %d) because "
                    "the timeout period of %y has been exceeded, and the order still has status %y", wfiid, h.name,
                    h.version, h.workflowid, to, h.workflowstatus);
            }
        }

        logInfo("wfiid %d has status %y", wfiid, h.workflowstatus);
    }

    private hash doCancel(softint wfiid, timeout to = 1m) {
        waitForStatus(wfiid, to);
        # add a note to the order instance giving the reason why the order was canceled
        callRestApi("POST", "orders/" + wfiid + "?action=Notes", {
            "note": "this order was canceled by the 'cancel-order' service",
        });
        return cancelOrder(wfiid);
    }
}

How can I see the raw HTTP headers and body for outgoing SOAP messages?

SOAP messages are sent with the SoapClient class and in Qorus should normally be acquired through a user connection object returned from the UserApi::getUserConnection() API function.

The recommended way to make the SOAP call and to allow for verbose debugging is to use the info output parameter in the SoapClient::call() or SoapClient::callOperation() method and log it with UserApi::logDebug() or higher as in the following example:

SoapClient sc = UserApi::getUserConnection(conn_name);
    hash<auto> response;
    {
        hash<auto> info;
        on_exit UserApi::logDebug("info: %N", info);
        response = sc.call(info, operation_name, msg);
    }

Note: Raw HTTP headers and message information is included when logging using the above technique; in case of HTTP basic authentication or user authentication information in the SOAP message, this information will also appear in the logs. Keep this in mind when dealing with sensitive information.

How can I see the raw HTTP headers and body for incoming HTTP messages?

Logging for raw HTTP information can be enabled by turning on the option on the HTTP listener using qrest to issue the appropriate REST API commands.

To list listeners:

qrest system/listeners?short

To turn on HTTP header and body logging for a particular listener (in this example, qorus-0):

qrest put system/listeners/qorus-0/setLogOptions option=-1

To turn off HTTP header and body logging for a particular listener (in this example, qorus-0):

qrest put system/listeners/qorus-0/setLogOptions option=0

The log information will appear in the system HTTP log unless listener is created in service. In this case it goes to service log!

Note: Raw HTTP headers and message information is included when logging using the above technique; in case of HTTP basic authentication or user authentication information in HTTP messages, this information will also appear in the logs. Keep this in mind when dealing with sensitive information.

How can I create a new workflow order from the command line?

qrest post workflows/WORKFLOW-NAME/createOrder
staticdata='{transaction_id="ABC12345"}'

How can I set a system property with a list or hash value from the command-line?

Qorus supports complex command-line parsing as in the following examples:

oprop set domain property '("item1","item2","item3)'
oprop set domain property key='{sub1=a,sub2=b,sub3=(1,2,three)}'

How do I clear Qorus's SQL cache when a database table has been changed?

qrest put system/sqlcache/clearCache

How do I reset a workflow from the command line?

qrest put workflows/WORKFLOW-NAME/reset

How do I set a system option from the command line?

qrest put system/options/verbose/set value=11

How do I get a list of interfaces Qorus is listening on at runtime?

# for a brief listing
qrest system/listeners?short
# for a verbose listing
qrest system/listeners

The values returned are all listeners; for Qorus and also for any services that have dedicated HTTP listeners.

Cloud VM FAQs

How do I update the VM with the newest software?

To update the software, log in to the VM with ssh with a user with sudo access (ex: ec2-user on AWS) and first shut down qorus with the following command:

sudo systemctl stop qorus-6.0-ee

Update the qorus software with the following command:

sudo dnf update -y

After a successful update, restart Qorus with the following command:

sudo systemctl start qorus-6.0-ee

Grab your FREE application integrations eBook.
You'll quickly learn how to connect your apps and data into robust processes!