Qorus Integration Engine® Enterprise Edition 6.1.0_prod
|
Back to the System Reference Manual Table of Contents
Services are sets of logic defined in methods that are loaded from the database. A service consists of a set of one or more methods that can be called from the Qorus system itself, from Qorus workflows, from other Qorus services, from other applications through the system API exported through YAML-RPC, XML-RPC, JSON-RPC, SOAP or other protocol handlers, or even from the command-line using the qrest or ocmd programs.
There are 2 types of services: system services and user services. Both kinds of services have their metadata and actual method logic stored in the database.
System services are written by Qore Technologies, delivered with the system. User services are defined and written by Qorus programmers.
Because system services provide Qorus system functionality, and because services can be deleted and reloaded from the database at any time, this means that these parts of the Qorus system itself can be upgraded without taking the system down and restarting it.
Passive services without running threads that just export methods to be called either internally or externally (or both) are like named and versioned API sets. Services that implement actions in service threads can do anything that the available system APIs allows them to do.
There are three service methods that have a special meaning to the Qorus system as listed in the following table. If any of these methods are defined, they will be called by the system itself when the service is loaded or unloaded.
Special Service Methods
Method | Description |
init() | If an init() method exists, it is called automatically when the service is loaded. If this method is explicitly called, no action is taken by the system, therefore this method can be called to ensure that the service is loaded. If this method returns a value, it will be ignored by the system. Any lock attribute defined on this method will be ignored. |
start() | If a start() method exists, it is launched in the background in a separate thread automatically when the service is loaded, after the init() method is called. Like the init() method, if this method is explicitly called, no action is taken by the system, therefore this method can be called to ensure that the service is loaded and running in the background. If this method returns a value, it will be ignored by the system. Any lock attribute defined on this method will be ignored. |
stop() | If a start() method exists, then a stop() method must also be defined. The stop() method is only called by the system when the service is deleted. If an external call to a service's stop() method is attempted, it results in an error. Any |
lock attribute defined on this method will be ignored.
Important service attributes are depicted in the following graphic.
Services have attributes as listed in the following table (for all attributes, see Qorus Services).
Service Attributes (table: SERVICES
)
Attribute | Description |
serviceid | The internal identifier for a service (primary key for the SERVICES table) |
name | The service's name |
version | The version identifier for the service. The type, name and version together uniquely identify a service in the database and are associated with one service ID. |
type | Either "SYSTEM" or "USER" . System services are delivered with the system by Qore Technologies, while user services are developed by Qorus programmers. |
description | The description of the service |
autostart | If this boolean flag is set to True, then the service will be automatically started when the system is started. |
remote | If this boolean flag is set to True, then the service will run in a remote qsvc process |
stateless | If this boolean flag is set to True, then the service must be started externally (when run under Kubernetes, Qorus will create the stateful sets automatically), and multiple instances of the service can run for load sharing and fault tolerance |
RWLock | This is an internal attribute of each service (not stored in the database); it is a read-write lock that belongs to every service and is automatically applied to method calls depending on the method's lock type attribute |
Tags | A list of user-defined tags for the service, stored in the SERVICE_TAGS table |
Additionally, the SERVICE_STATE_DATA
table is used to store persistent data for service data to aid in recovering service actions in case of errors. This table has one row for each service. Service state can be stored using:
Services then have one or more methods, which provide the logic for the service.
Service methods can be depicted as in the following graphic.
Service methods have the attributes listed in the following table. Note that service methods do not have versions; their name must be unique within the scope of the parent service object. For all method attributes, see Service Methods.
Service Method Attributes (table: SERVICE_METHODS)
Attribute | Description |
service_methodid | The unique ID of the method (primary key for the table) |
serviceid | The service the method belongs to |
name | The method's name, which must be unique within the service. |
description | An optional description for the service |
locktype | This can be OMQ::SLRead, OMQ::SLWrite, or OMQ::SLNone. Depending on this value the system will wrap calls to the method with the appropriate call to the parent service object's read-write lock object. |
internal | A Boolean flag that restricts calling the method to internal calls only. Any method with this flag set will not be exported through the HTTP server's web service protocol handlers. |
writeflag | A Boolean flag that can be used to restrict call access only to users with write access to the application |
code | This is the code that is loaded when the method is loaded along with the parent service object. This logic must contain a function with the same name as the service method. |
When services are loaded, all methods belonging to the service are loaded at the same time. Additionally, the Qorus system will automatically load the latest version of the service from the database.
As described above, if the service has init() or start() methods defined, they will be automatically called by the system when the service is loaded, before any other methods can be called. This allows the service to perform initialization before other methods are called and therefore ensure consistent results. Additionally, when a service is loaded, the system event SERVICE_START is raised.
When a service is deleted, if it has start() and stop() methods, or if any service threads were started manually using service APIs, the stop()
method is called and the system waits for all service threads to terminate. After all service threads terminate, the service is unloaded from the system immediately. When a service is unloaded, the system event SERVICE_STOP is raised. If any system errors occur related to loading or running a service (such as a service's thread terminating prematurely, for example), the system event SERVICE_ERROR is raised.
If a service call is made and the service referenced is not already loaded, the latest version of the service will be loaded from the Oracle database and initialized and started (if init()
and/or start()
methods exist, respectively).
The call will block until the service is loaded (and initialized and/or started if init() and/or start() methods exist).
In general, any calls to services while they are in transition states (being initialized/started or deleted) will block until the service exits the transition state. In the case of a service call to a service being deleted, the call will block until the service has been deleted, after which the latest version of the service will be reloaded (and initialized, etc if necessary) and then the call will be made.