Wrapper for communication with cap messaging service


Wrapper for communication with cap messaging service
- Features
- Installing
- Configuration
- Implementation
- License
- Simple configuration
- Using placeholders in topics
- Optional logging of whole event message (DEBUG=messaging)
- Set 'x-correlation-id' in event header to follow events over applications
- Managing composite configuration in combination of local or file based messaging
- Fully integrated in cdc runtime without hard binding of services to register for events
- Usage of event prefixes
- Auto configuration with cds plugin feature
- Fixes listener registration, if service name in package.json differs to service name
Deprecated
- Set 'topic' in event header (deprecated: use type and/or source instead)
Using npm:
``bash`
$ npm install @amag-ch/cds-messaging
Using yarn:
`bash`
$ yarn add @amag-ch/cds-messaging
json
{
"cds": {
"requires": {
"queue": {
"kind": "persistent-outbox"
},
"kinds": {
"composite-messaging": {
"impl": "@amag-ch/cds-messaging/composite.js",
"format": "cloudevents",
"subscribePrefix": "$namespace/",
"publishPrefix": "$namespace/"
},
"enterprise-messaging-http": {
"format": "cloudevents",
"subscribePrefix": "$namespace/",
"publishPrefix": "$namespace/"
},
"enterprise-messaging-amqp": {
"format": "cloudevents",
"subscribePrefix": "$namespace/",
"publishPrefix": "$namespace/",
"amqp": {
"incomingSessionWindow": 100
}
}
}
}
}
}
`$3
Simple default configuration over standard messaging object in package.jsonAt least only the namespace is needed
`json
{
"cds": {
"requires": {
"messaging": {
"kind": "enterprise-messaging-http",
"impl": "@amag-ch/cds-messaging/service.js",
"credentials": {
"namespace": "btp/-/"
}
}
}
}
}
`This results in following standard configuration
`json
{
"cds": {
"requires": {
"messaging": {
"kind": "enterprise-messaging-http",
"impl": "@amag-ch/cds-messaging/service.js",
"subscribePrefix": "$namespace/",
"publishPrefix": "$namespace/",
"format": "cloudevents",
"credentials": {
"namespace": "btp/-/"
}
}
}
}
}
`$3
Simpliest configuration
`json
{
"cds": {
"requires": {
"messaging-self-publishes": {
"kind": "enterprise-messaging-http"
}
}
}
}
`This results in following standard configuration
`json
{
"cds": {
"requires": {
"messaging-self-publishes": {
"kind": "enterprise-messaging-http",
"subscribePrefix": "$namespace/",
"publishPrefix": "$namespace/",
"format": "cloudevents",
"credentials": {
"namespace": "btp/-/"
},
"queue": {
"name": "$namespace/self-publishes",
}
}
}
}
}
`Of course, the defaults could be overwritten
`json
{
"cds": {
"requires": {
"messaging-self-publishes": {
"kind": "enterprise-messaging-http",
"queue": {
"maxDeliveredUnackedMsgsPerFlow": "1"
}
}
}
}
}
`$3
Simpliest configuration
`json
{
"cds": {
"requires": {
"messaging-foreign-system": {
"kind": "enterprise-messaging-http",
"subscribePrefix": "foreign/system/namespace/"
}
}
}
}
`This results in following standard configuration
`json
{
"cds": {
"requires": {
"messaging-foreign-system": {
"kind": "enterprise-messaging-http",
"subscribePrefix": "foreign/system/namespace/",
"publishPrefix": "$namespace/",
"format": "cloudevents",
"credentials": {
"namespace": "btp/-/"
},
"queue": {
"name": "$namespace/foreign-system"
}
}
}
}
}
`$3
`json
{
"cds": {
"requires": {
"messaging": {
"kind": "composite-messaging",
"default": "messaging-default",
"credentials": {
"namespace": "btp/-/"
},
"routes": {
"messaging-foreign-system": [
"foreign-system:object/changed",
"other/object/changed"
]
}
},
"messaging-default": {
"kind": "enterprise-messaging-amqp",
"[development]": {
"kind": "file-based-messaging"
}
},
"messaging-foreign-system": {
"kind": "enterprise-messaging-http",
"subscribePrefix": "foreign/system/namespace/"
}
}
}
}
`- A default service definition is required (property default). The name of the default service doesn't matter, but it shouldn't be a service for external events
- Events are everytime emitted through the default service, except those routes to a local-messaging definition
- Events in on handlers, which are not defined in the routes, are handled by the default service
- If the default service is not real messaging service (e.g local or file-based), then only the default service would be created and handle all. Subscribe prefixes are still been considered.
- Events could be prefixed with pattern [a-zA-Z_-]: to avoid naming collisions with own events in configuration
Implementation
$3
`js
const messaging = await cds.connect.to('messaging')
const { buildEventFromTemplate } = require('@amag-ch/cds-messaging')cds.once('listening', () => {
/*
* Standard emitting
* Signature is same as for standard cap messaging service
*
* Full topic based on configuration is: $namespace/object/changed => cap///object/changed
*/
messaging.emit('object/changed', { ID })
/*
* Emitting with replacements
* Usefull, if cannot fully control the input value
*
* Following call results in event: objectwithillegalcharacters/changed
*/
messaging.emit({ template: ':1/changed', replacements: ['object-with-illegal_characters']}, { ID })
/*
* Emitting with replacements
* Usefull, if cannot fully control the input value
*
* Following call results in event: objectwithillegalcharacters/changed
*/
messaging.emit(buildEventFromTemplate(':1/changed', ['object-with-illegal_characters']), { ID })
})
/**
* Topics, we are listening here are (based on subscribePrefix):
* - $namespace/object/changed => cap///object/changed
* - $namespace/objectwithillegalcharacters/changed => cap///objectwithillegalcharacters/changed
*/
messaging.on([
'object/changed',
'objectwithillegalcharacters/changed'
], async (msg) => {
console.log(msg)
...
})
`$3
`js
const messaging = await cds.connect.to('messaging')/**
* Topic, we are listening here is (based on subscribePrefix): foreign/system/namespace/object/changed
*/
messaging.on('foreign-system:object/changed', async (msg) => {
console.log(msg)
...
/**
* This results in topic (based on publishPrefix): $namespace/object/changed => cap///object/changed
*/
messaging.emit('object/changed', { ID })
})
`$3
`js
/**
* Prefixes needed, to register to other unknown services
*/
this.on([
'foreign-system:object/changed',
'self:objectwithillegalcharacters/changed'
], async (msg) => { console.log(msg)
...
/**
* Event definition in cds service needed
*
* @topic: 'object/changed'
* event ![object/changed] { ID: UUID }
*/
this.emit('object/changed', { ID })
/**
* Event definition in cds service needed
*
* @topic: 'object/created'
* event objectCreated { ID: UUID }
*/
this.emit('objectCreated', { ID })
})
``- Annotation @topic should be used to avoid prepending of service name to the resulting event
- Usage of template based events is not possible here