diff --git a/bookshop/package.json b/bookshop/package.json index cc3ce867..b1712e39 100644 --- a/bookshop/package.json +++ b/bookshop/package.json @@ -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": { diff --git a/fiori/package.json b/fiori/package.json index b8301455..fb3a21f8 100644 --- a/fiori/package.json +++ b/fiori/package.json @@ -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": { diff --git a/reviewed/package.json b/reviewed/package.json index 8bd2d2ff..363d42e3 100644 --- a/reviewed/package.json +++ b/reviewed/package.json @@ -4,7 +4,7 @@ "dependencies": { "@capire/bookshop": "../bookshop", "@capire/reviews": "../reviews", - "@sap/cds": "^3.33.1", + "@sap/cds": "^4", "express": "^4.17.1" }, "cds": { diff --git a/reviewed/server.js b/reviewed/server.js index 080b6be1..2d522474 100644 --- a/reviewed/server.js +++ b/reviewed/server.js @@ -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 ('reviewed', (msg) => { console.debug ('> received:', msg.event, msg.data) const { subject, rating } = msg.data return UPDATE(Books,subject).with({rating}) diff --git a/reviews/package.json b/reviews/package.json index 373ba66c..970b956c 100644 --- a/reviews/package.json +++ b/reviews/package.json @@ -7,7 +7,7 @@ "index.cds" ], "dependencies": { - "@sap/cds": ">=3.33.1", + "@sap/cds": "^4", "express": "^4.17.1" }, "scripts": { diff --git a/reviews/srv/reviews-service.cds b/reviews/srv/reviews-service.cds index 0081a62c..027fb961 100644 --- a/reviews/srv/reviews-service.cds +++ b/reviews/srv/reviews-service.cds @@ -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; diff --git a/reviews/srv/reviews-service.js b/reviews/srv/reviews-service.js index 33f383d9..0eec865f 100644 --- a/reviews/srv/reviews-service.js +++ b/reviews/srv/reviews-service.js @@ -1,25 +1,23 @@ 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 }) - }) + global.it || console.log ('< emitting:', 'reviewed', { subject, rating }) + messaging.tx(req).emit ('reviewed', { subject, rating }) }) // Increment counter for reviews considered helpful diff --git a/test/messaging.test.js b/test/messaging.test.js index 632b093f..abc0d305 100644 --- a/test/messaging.test.js +++ b/test/messaging.test.js @@ -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('reviewed', (msg,next)=> { received.push(msg); return next() }) }) it ('should add more messaging event handlers', ()=>{ - srv.on('reviewed', (_,next)=> { ++M; return next() }) + messaging.on('reviewed', (_,next)=> { ++M; return next() }) }) it ('should add review', async ()=>{