new messaging
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
"description": "A simple self-contained bookshop service.",
|
||||
"dependencies": {
|
||||
"@capire/common": "../common",
|
||||
"@sap/cds": ">=3.33.1",
|
||||
"@sap/cds": "^4",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"@capire/bookshop": "../bookshop",
|
||||
"@capire/orders": "../orders",
|
||||
"@capire/common": "../common",
|
||||
"@sap/cds": ">=3.33.1",
|
||||
"@sap/cds": "^4",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"dependencies": {
|
||||
"@capire/bookshop": "../bookshop",
|
||||
"@capire/reviews": "../reviews",
|
||||
"@sap/cds": "^3.33.1",
|
||||
"@sap/cds": "^4",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"cds": {
|
||||
|
||||
@@ -11,6 +11,7 @@ cds.once('served', async ({CatalogService}) => {
|
||||
// reflect entity definitions used below...
|
||||
const { Books } = cds.entities('sap.capire.bookshop')
|
||||
const { Reviews } = cds.entities('ReviewsService')
|
||||
const messaging = await cds.connect.to('messaging')
|
||||
|
||||
// prepend the following handler so it overrides the default handler
|
||||
CatalogService.prepend (srv => srv.on ('READ', 'Books/reviews', (req) => {
|
||||
@@ -19,9 +20,7 @@ cds.once('served', async ({CatalogService}) => {
|
||||
return SELECT(columns).from(Reviews).limit(limit).where({subject:String(id)})
|
||||
}))
|
||||
|
||||
// subscribe to events emitted by ReviewsService
|
||||
const ReviewsService = await cds.connect.to ('ReviewsService')
|
||||
ReviewsService.on ('reviewed', (msg) => {
|
||||
messaging.on ('review/reviewed', (msg) => {
|
||||
console.debug ('> received:', msg.event, msg.data)
|
||||
const { subject, rating } = msg.data
|
||||
return UPDATE(Books,subject).with({rating})
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"index.cds"
|
||||
],
|
||||
"dependencies": {
|
||||
"@sap/cds": ">=3.33.1",
|
||||
"@sap/cds": "^4",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -2,17 +2,10 @@ using { sap.capire.reviews as my } from '../db/schema';
|
||||
|
||||
service ReviewsService {
|
||||
|
||||
// Sync API
|
||||
entity Reviews as projection on my.Reviews excluding { likes }
|
||||
action like (review: type of Reviews:ID);
|
||||
action unlike (review: type of Reviews:ID);
|
||||
|
||||
// Async API
|
||||
event reviewed : {
|
||||
subject: type of Reviews:subject;
|
||||
rating: Decimal(2,1)
|
||||
};
|
||||
|
||||
// Input validation
|
||||
annotate Reviews with {
|
||||
subject @mandatory;
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
const cds = require ('@sap/cds')
|
||||
module.exports = cds.service.impl (function(){
|
||||
module.exports = cds.service.impl (async function(){
|
||||
|
||||
// Get the CSN definition for Reviews from the db schema for sub-sequent queries
|
||||
// ( Note: we explicitly specify the namespace to support embedded reuse )
|
||||
const { Reviews, Likes } = this.entities ('sap.capire.reviews')
|
||||
const messaging = await cds.connect.to('messaging')
|
||||
|
||||
this.before (['CREATE','UPDATE'], 'Reviews', req => {
|
||||
if (!req.data.rating) req.data.rating = Math.round(Math.random()*4)+1
|
||||
})
|
||||
|
||||
// Emit an event to inform subscribers about new avg ratings for reviewed subjects
|
||||
// ( Note: req.on.succeeded ensures we only do that if there's no error )
|
||||
this.after (['CREATE','UPDATE','DELETE'], 'Reviews', async(_,req) => {
|
||||
const {subject} = req.data
|
||||
const {rating} = await cds.transaction(req) .run (
|
||||
SELECT.one (['round(avg(rating),2) as rating']) .from (Reviews) .where ({subject})
|
||||
)
|
||||
req.on ('succeeded', ()=>{
|
||||
global.it || console.log ('< emitting:', 'reviewed', { subject, rating })
|
||||
this.emit ('reviewed', { subject, rating })
|
||||
})
|
||||
const msgTx = messaging.tx(req)
|
||||
global.it || console.log ('< emitting:', 'reviewed', { subject, rating })
|
||||
msgTx.emit ('review/reviewed', { subject, rating })
|
||||
})
|
||||
|
||||
// Increment counter for reviews considered helpful
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
const cwd = process.cwd(); process.chdir (__dirname) //> only for internal CI/CD@SAP
|
||||
const cds = require ('./cds'), {expect} = cds.test
|
||||
const _model = '@capire/reviews'
|
||||
let messaging
|
||||
|
||||
|
||||
describe('Messaging', ()=>{
|
||||
|
||||
beforeAll(async () => {
|
||||
messaging = await cds.connect.to('messaging')
|
||||
})
|
||||
after(()=> process.chdir(cwd))
|
||||
|
||||
it ('should bootstrap sqlite in-memory db', async()=>{
|
||||
@@ -20,11 +24,11 @@ describe('Messaging', ()=>{
|
||||
|
||||
let N=0, received=[], M=0
|
||||
it ('should add messaging event handlers', ()=>{
|
||||
srv.on('reviewed', (msg,next)=> { received.push(msg); return next() })
|
||||
messaging.on('review/reviewed', (msg,next)=> { received.push(msg); return next() })
|
||||
})
|
||||
|
||||
it ('should add more messaging event handlers', ()=>{
|
||||
srv.on('reviewed', (_,next)=> { ++M; return next() })
|
||||
messaging.on('review/reviewed', (_,next)=> { ++M; return next() })
|
||||
})
|
||||
|
||||
it ('should add review', async ()=>{
|
||||
|
||||
Reference in New Issue
Block a user