From 1d1176134626e41254137c4e6831317cac182aa8 Mon Sep 17 00:00:00 2001 From: D050513 Date: Thu, 18 Jun 2026 10:00:15 +0200 Subject: [PATCH 1/6] messaging.emit('FlightUpdated') --- package.json | 6 +++++- srv/data-service.js | 20 +++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index ff3f7f4..78bfab9 100644 --- a/package.json +++ b/package.json @@ -6,11 +6,15 @@ "start": "cds-serve" }, "dependencies": { - "@cap-js/hana": ">=2.1.2", "@sap/cds": ">=9" }, "devDependencies": { "@cap-js/sqlite": ">=2" }, + "cds": { + "requires": { + "messaging": "file-based-messaging" + } + }, "license": "Apache-2.0" } diff --git a/srv/data-service.js b/srv/data-service.js index 7052fdf..0b47dd3 100644 --- a/srv/data-service.js +++ b/srv/data-service.js @@ -1,18 +1,28 @@ const cds = require ('@sap/cds') -class DataService extends cds.ApplicationService { init() { +class DataService extends cds.ApplicationService { async init() { + + const messaging = await cds.connect.to ('messaging') const { Flights } = cds.entities ('sap.capire.flights') this.on ('BookingCreated', async req => { const { flight, date, seats = [null] } = req.data - await UPDATE (Flights, { flight_ID:flight, date }) - .set `occupied_seats = occupied_seats + ${seats.length}` + const confirmed = await UPDATE (Flights, { flight_ID:flight, date }) + .set `occupied_seats = occupied_seats + ${seats.length}` + .where `free_seats >= ${seats.length}` + if (!confirmed) req.reject('Flight is fully booked') + + // messages can overtake each other -> don't propagate free seats in payload + messaging.emit('FlightUpdated', { flight_ID:flight, date }) }) this.on ('BookingDeleted', async (req) => { const { flight, date, seats = [null] } = req.data - await UPDATE (Flights, { flight_ID:flight, date }) - .set `occupied_seats = occupied_seats - ${seats.length}` + await UPDATE (Flights, { flight_ID:flight, date }) + .set `occupied_seats = occupied_seats - ${seats.length}` + + // messages can overtake each other -> don't propagate free seats in payload + messaging.emit('FlightUpdated', { flight_ID:flight, date }) }) return super.init() From d04661d98094abc821aafa5b0b0ca69306c66ad2 Mon Sep 17 00:00:00 2001 From: Sebastian Van Syckel Date: Mon, 13 Jul 2026 14:44:22 +0200 Subject: [PATCH 2/6] fix: use existing FlightsUpdated --- package.json | 2 +- srv/data-service.js | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 78bfab9..d1c5bf6 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "cds": { "requires": { - "messaging": "file-based-messaging" + "messaging": true } }, "license": "Apache-2.0" diff --git a/srv/data-service.js b/srv/data-service.js index 0b47dd3..f17d514 100644 --- a/srv/data-service.js +++ b/srv/data-service.js @@ -1,8 +1,6 @@ const cds = require ('@sap/cds') class DataService extends cds.ApplicationService { async init() { - const messaging = await cds.connect.to ('messaging') - const { Flights } = cds.entities ('sap.capire.flights') this.on ('BookingCreated', async req => { @@ -12,8 +10,8 @@ class DataService extends cds.ApplicationService { async init() { .where `free_seats >= ${seats.length}` if (!confirmed) req.reject('Flight is fully booked') - // messages can overtake each other -> don't propagate free seats in payload - messaging.emit('FlightUpdated', { flight_ID:flight, date }) + const { free_seats } = await SELECT('free_seats').from(Flights, { flight_ID:flight, date }) + this.emit('FlightsUpdated', { flight, date, free_seats }) }) this.on ('BookingDeleted', async (req) => { @@ -21,8 +19,8 @@ class DataService extends cds.ApplicationService { async init() { await UPDATE (Flights, { flight_ID:flight, date }) .set `occupied_seats = occupied_seats - ${seats.length}` - // messages can overtake each other -> don't propagate free seats in payload - messaging.emit('FlightUpdated', { flight_ID:flight, date }) + const { free_seats } = await SELECT('free_seats').from(Flights, { flight_ID:flight, date }) + this.emit('FlightsUpdated', { flight, date, free_seats }) }) return super.init() From 2e8fd203ab9f1424808744feb1d9808157a52dca Mon Sep 17 00:00:00 2001 From: Sebastian Van Syckel Date: Mon, 13 Jul 2026 15:22:52 +0200 Subject: [PATCH 3/6] cleanup --- srv/data-service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srv/data-service.js b/srv/data-service.js index f17d514..99baf07 100644 --- a/srv/data-service.js +++ b/srv/data-service.js @@ -1,5 +1,5 @@ const cds = require ('@sap/cds') -class DataService extends cds.ApplicationService { async init() { +class DataService extends cds.ApplicationService { init() { const { Flights } = cds.entities ('sap.capire.flights') From 1ee2456bfd48a9d5d31cb41fb5704bca897501ca Mon Sep 17 00:00:00 2001 From: Sebastian Van Syckel Date: Tue, 14 Jul 2026 14:37:06 +0200 Subject: [PATCH 4/6] rm free_seats --- srv/data-service.cds | 3 ++- srv/data-service.js | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/srv/data-service.cds b/srv/data-service.cds index 6890d80..bc8394d 100644 --- a/srv/data-service.cds +++ b/srv/data-service.cds @@ -31,7 +31,8 @@ service sap.capire.flights.data { // Custom actions and events to sync with consumers about flight seat availability action BookingCreated ( flight: Flights:ID, date: Flights:date, seats: array of Integer); action BookingDeleted ( flight: Flights:ID, date: Flights:date, seats: array of Integer); - event FlightsUpdated { flight: Flights:ID; date: Flights:date; free_seats: Integer; } + // Restrict payload to identity as messages can overtake each other (-> outdated payload) + event FlightsUpdated { flight: Flights:ID; date: Flights:date; }; } diff --git a/srv/data-service.js b/srv/data-service.js index 99baf07..f842a66 100644 --- a/srv/data-service.js +++ b/srv/data-service.js @@ -10,8 +10,7 @@ class DataService extends cds.ApplicationService { init() { .where `free_seats >= ${seats.length}` if (!confirmed) req.reject('Flight is fully booked') - const { free_seats } = await SELECT('free_seats').from(Flights, { flight_ID:flight, date }) - this.emit('FlightsUpdated', { flight, date, free_seats }) + this.emit('FlightsUpdated', { flight, date }) }) this.on ('BookingDeleted', async (req) => { @@ -19,8 +18,7 @@ class DataService extends cds.ApplicationService { init() { await UPDATE (Flights, { flight_ID:flight, date }) .set `occupied_seats = occupied_seats - ${seats.length}` - const { free_seats } = await SELECT('free_seats').from(Flights, { flight_ID:flight, date }) - this.emit('FlightsUpdated', { flight, date, free_seats }) + this.emit('FlightsUpdated', { flight, date }) }) return super.init() From 15332b499f3b49686cbf0e4e460555241b7bece2 Mon Sep 17 00:00:00 2001 From: Sebastian Van Syckel Date: Tue, 14 Jul 2026 14:45:54 +0200 Subject: [PATCH 5/6] formatting --- srv/data-service.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/srv/data-service.js b/srv/data-service.js index f842a66..c66d471 100644 --- a/srv/data-service.js +++ b/srv/data-service.js @@ -9,7 +9,6 @@ class DataService extends cds.ApplicationService { init() { .set `occupied_seats = occupied_seats + ${seats.length}` .where `free_seats >= ${seats.length}` if (!confirmed) req.reject('Flight is fully booked') - this.emit('FlightsUpdated', { flight, date }) }) @@ -17,7 +16,6 @@ class DataService extends cds.ApplicationService { init() { const { flight, date, seats = [null] } = req.data await UPDATE (Flights, { flight_ID:flight, date }) .set `occupied_seats = occupied_seats - ${seats.length}` - this.emit('FlightsUpdated', { flight, date }) }) From c3e1cfddb72874b12037e70893628f0eb46dcc01 Mon Sep 17 00:00:00 2001 From: sjvans <30337871+sjvans@users.noreply.github.com> Date: Tue, 14 Jul 2026 15:24:03 +0200 Subject: [PATCH 6/6] Apply suggestion from @sjvans --- srv/data-service.cds | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srv/data-service.cds b/srv/data-service.cds index adb5d6b..b3abb10 100644 --- a/srv/data-service.cds +++ b/srv/data-service.cds @@ -30,7 +30,7 @@ service FlightsService { // Custom actions and events to sync with consumers about flight seat availability action BookingCreated ( flight: Flights:ID, date: Flights:date, seats: array of Integer); action BookingDeleted ( flight: Flights:ID, date: Flights:date, seats: array of Integer); - // Restrict payload to identity as messages can overtake each other (-> outdated payload) + // Restrict payload to identity as messages can overtake each other in the ether event FlightsUpdated { flight: Flights:ID; date: Flights:date; }; }