Use as CAP Outbox
- How to enable the event-queue as outbox mechanism for CAP
- How to Configure an Outboxed Service
- Example of a Custom Outboxed Service
The event-queue can be used to replace the CAP outbox solution to achieve a unified and streamlined architecture for asynchronous processing. If this feature is activated, the event-queue replaces the outbox implementation of CAP with its own implementation during the bootstrap process. This allows leveraging the features of the event-queue, such as transaction modes, load balancing, and others, with outboxed CDS services.
How to enable the event-queue as outbox mechanism for CAP
The initialization parameter useAsCAPOutbox
enables the event-queue to act as a CAP outbox. To set this parameter, refer to the setup part of the documentation. This is the only configuration needed to enable the event-queue as a CAP outbox.
{
"cds": {
"eventQueue": {
"useAsCAPOutbox": true
}
}
}
How to Configure an Outboxed Service
Services can be outboxed without any additional configuration. In this scenario, the service is outboxed using the default parameters of the CAP outbox and the event-queue. Currently, the CAP outbox implementation supports the following parameters, which are mapped to the corresponding configuration parameters of the event-queue:
CAP outbox | event-queue | CAP default |
---|---|---|
chunkSize | selectMaxChunkSize | 100 |
maxAttempts | retryAttempts | 20 |
parallel | parallelEventProcessing | yes (mapped to 5) |
- | useEventQueueUser | false |
The parallel
parameter is treated specially. The CAP outbox supports true
or false
as values for this parameter. Since the event-queue allows specifying concurrency with a number, parallel=true
is mapped to parallelEventProcessing=5
, and parallel=false
is mapped to parallelEventProcessing=1
. For full flexibility, the configuration prioritizes the parallelEventProcessing
parameter over parallel
.
The useEventQueueUser
parameter can be set to true or false. When set to true, the user defined in the general configuration will be used as the cds context user (context.user.id). This influences actions such as updating managed database fields like modifiedBy. The default value for this parameter is false.
All supported parameters available for EventQueueProcessors are also available for CAP outboxed services. This means that you can use the same configuration settings and options that you would use with EventQueueProcessors when configuring CAP outboxed services, ensuring consistent behavior and flexibility across both use cases.
Parameters are managed via the cds.require
section, not through the config yml file as with other events. For details on maintaining the cds.requires
section, refer to the CAP documentation. Below is an example of using the event-queue to outbox the @cap-js/audit-logging
service:
{
"cds": {
"requires": {
"audit-log": {
"outbox": {
"kind": "persistent-outbox",
"transactionMode": "alwaysRollback",
"maxAttempts": 5,
"checkForNextChunk": true,
"parallelEventProcessing": 5
}
}
}
}
}
The parameters in the outbox section of a service are passed as configuration to the event-queue. The persistent-outbox
kind allows the event-queue to persist events instead of executing them in memory, mirroring the behavior of the CAP outbox. The parameters transactionMode
, checkForNextChunk
, and parallelEventProcessing
are exclusive to the event-queue.
Example of a Custom Outboxed Service
Internal Service with cds.Service
The implementation below demonstrates a basic cds.Service
that can be outboxed. If you want to configure outboxing via cds.env.requires
, the service needs to inherit from cds.Service
.
class TaskService extends cds.Service {
async init() {
await super.init();
this.on("process", async function (req) {
// add your code here
});
}
}
Outboxing can be enabled via configuration using cds.env.requires
, for example, through package.json
.
{
"cds": {
"requires": {
"task-service": {
"impl": "./srv/PATH_SERVICE/taskService.js",
"outbox": {
"kind": "persistent-outbox",
"transactionMode": "alwaysRollback",
"maxAttempts": 5,
"checkForNextChunk": true,
"parallelEventProcessing": 5
}
}
}
}
}
Application Service with cds.ApplicationService
In contrast, cds.ApplicationService
, which is served based on protocols like odata-v4, cannot be outboxed via configuration (cds.env.requires
). Nevertheless, outboxing can be performed manually as shown in the example below:
const service = await cds.connect.to("task-service");
const outboxedService = cds.outboxed(service, {
kind: "persitent-outbox",
transactionMode: "alwaysRollback",
checkForNextChunk: true,
});
await outboxedService.send("process", {
ID: 1,
comment: "done",
});
How to Delay Outboxed Service Calls
The event queue has a feature that enables the publication of delayed events. This feature is also applicable to CAP outboxed services.
To implement this feature, include the x-eventqueue-startAfter
header attribute during the send or emit process.
const outboxedService = await cds.connect.to("task-service");
await outboxedService.send(
"process",
{
ID: 1,
comment: "done",
},
// delay the processing 4 minutes
{ "x-eventqueue-startAfter": new Date(Date.now() + 4 * 60 * 1000).toISOString() }
);
Additional parameters Outboxed Service Calls
Similar to delaying published events, it is also possible to provide other parameters when publishing events. All event publication properties can be found here.
Error Handling in a Custom Outboxed Service
If the custom service is invoked via service.send()
, errors can be raised with req.reject()
and req.error()
. The reject
and error
functions cannot be used if the service call is made via service.emit()
. Refer to the example below for an implementation reference.
class TaskService extends cds.Service {
async init() {
await super.init();
this.on("rejectEvent", (req) => {
req.reject(404, "error occured");
});
this.on("errorEvent", (req) => {
req.error(404, "error occured");
});
}
}
Errors raised in a custom outboxed service are thrown and will be logged from the event queue. The event entry will be marked as an error and will be retried based on the event configuration.
Event-Queue properties
The event queue properties that are available for the native event queue processor (refer to this documentation) are also accessible for outboxed services utilizing the event queue. These properties can be accessed via the cds context. The following properties are available:
- processor: instance of event-queue processor
- key
- queueEntries
- payload
class TaskService extends cds.Service {
async init() {
await super.init();
this.on("send", (req) => {
const { processor, queueEntries, payload, key } = req.context._eventQueue;
});
}
}