is it a good practice at all and if yes what is the correct way to break a transaction with different error states/messages for different situations?
I have a transaction running over an 'offer' entry doing 'seats' reservation:
I want to break it if one of the following 3 conditions is true and return state/message to the caller function.
- if the asking user already made a reservation of seats of this offer.
- if there is not enought seats.
- if this offer does not exists.
And if everything is ok the transaction should complete normally and return state/message to the caller function that reservation is made.
I'm not sure how to break the transaction in case of one of the conditions is true.
- if I use throw new Error('description of the problem.') then this will be an Exception and it's not handled by catch() handler of the transaction Promise and I'm not sure how to handle this exception because it's an asynchronous function here. so I think i should not use an exception.
Here is what I mean:
dealSeats = function(entryRef, data) {
const TAG = '[dealSeats]: ';
return entryRef.transaction((entry)=>{
if (entry) {
if ((entry.deals) && (entry.deals[data.uid])) {
**? how to break the transaction with state/message 'You already have a deal.' ? and how to handle it below ?**
} else if (entry.details.seatsCount >= data.details.seatsCount) {
entry.details.seatsCount -= data.details.seatsCount;
var deal = [];
deal.status = 'asked';
deal.details = data.details;
if (!entry.deals) {
entry.deals = {};
}
entry.deals[data.uid] = deal;
} else {
**? how to break the transaction with state/message 'Not enought seats.' ? and how to handle it below ?**
}
}
return entry;
**? how to check if 'entry' is really null ? i.e. offer does not exists ?** and break and handle it.
})
.then((success)=>{
return success.snapshot.val();
})
.catch((error)=>{
return Promise.reject(error);
});
}
here is my data in realtime database:
activeOffers
-LKohyZ58cnzn0vCnt9p
details
direction: "city"
seatsCount: 2
timeToGo: 5
uid: "-ABSIFJ0vCnt9p8387a" ---- offering user
here is my test data sent by Postman:
{
"data":
{
"uid": "-FGKKSDFGK12387sddd", ---- the requesting/asking user
"id": "-LKpCACQlL25XTWJ0OV_",
"details":
{
"direction": "city",
"seatsCount": 1,
"timeToGo": 5
}
}
}
==== updated with final source ====
many thanks to Renaud Tarnec!
So here is my final source that is working fine. If someone sees a potential problem please let me know. Thanks.
dealSeats = function(entryRef, data) {
const TAG = '[dealSeats]: ';
var abortReason;
return entryRef.transaction((entry)=>{
if (entry) {
if ((entry.deals) && (entry.deals[data.uid])) {
abortReason = 'You already made a reservation';
return; // abort transaction
} else if (entry.details.seatsCount >= data.details.seatsCount) {
entry.details.seatsCount -= data.details.seatsCount;
var deal = [];
deal.status = 'asked';
deal.details = data.details;
if (!entry.deals) {
entry.deals = {};
}
entry.deals[data.uid] = deal;
// Reservation is made
} else {
abortReason = 'Not enought seats';
return; // abort transaction
}
}
return entry;
})
.then((result)=>{ // resolved
if (!result.committed) { // aborted
return abortReason;
} else {
let value = result.snapshot.val();
if (value) {
return value;
} else {
return 'Offer does not exists';
}
}
})
.catch((reason)=>{ // rejected
return Promise.reject(reason);
});
}
The only pain is a warning during deploy in VSCode terminal about this abortions by returning no value:
warning Arrow function expected no return value consistent-return
currently I'm not sure if I could do anything about it.