Вариант использования:
Пользователь получит пароль для двери (например, door2
, пароль 222
), когда они находятся в определенном месте (например, LocationA
),После этого облачная функция удалит дверь из документов empty
и добавит ее в документ occupied
.
Исходная база данных:
"LocationA" : {
"empty" : {
"door2" : {
"password" : "222"
},
"door3" : {
"password" : "333"
}
},
"occupied" : {
"door1" : {
"password" : "111"
}
}
}
После того, как пользователь получит пароль для пустой двери:
"LocationA" : {
"empty" : {
"door3" : {
"password" : "333"
}
},
"occupied" : {
"door1" : {
"password" : "111"
},
"door2" : {
"password" : "222"
}
}
}
Проблема:
Что, если есть 2 пользователя, одновременно получает door2
пароль?Будет ли этот сценарий происходить?
Мне бы хотелось, чтобы пользователь 1 получил door2
, а пользователь 2 - door3
соответственно.
Это код, который я использую для получениядверь:
// Read Lockers QR User(CRUD)
exports.getQRCode = functions.https.onRequest((req, res) => {
admin.database().ref('lockers/' + 'LocationA/' + 'empty').limitToFirst(1).once("value",snap=> {
console.log('QR Code for door:',snap.val());
var qrCodesForDoor = snap.val();
res.send(qrCodesForDoor);
});
});
Обновлена база на ответ Гримторра
exports.getQRCode = functions.https.onRequest((req, res) => {
admin.database().ref('lockers/LocationA/empty').limitToFirst(1).once("value", snap=> {
// Get the name of the first available door and use a transaction to ensure it is not occupied
console.log('QR Code for door:',snap.val());
var door = Object.keys(snap.val())[0];
console.log('door:',door);
// var door = snap.key();
var occupiedRef = admin.database().ref('lockers/LocationA/occupied/'+door);
occupiedRef.transaction(currentData=> {
if (currentData === null) {
console.log("Door does not already exist under /occupied, so we can use this one.");
return snap.child(door).val(); // Save the chosen door to /occupied
} else {
console.log('The door already exists under /occupied.');
return nil; // Abort the transaction by returning nothing
}
}, (error, committed, snapshot) => {
console.log('snap.val():',snap.val());
if (error) {
console.log('Transaction failed abnormally!', error);
res.send("Unknown error."); // This handles any abormal error
} else if (!committed) {
console.log('We aborted the transaction (because the door is already occupied).');
res.redirect(req.originalUrl); // Refresh the page so that the request is retried
} else {
// The door is not occupied, so can be given to this user
admin.database().ref('lockers/LocationA/empty/'+door).remove(); // Delete the door from /empty
console.log('QR Code for door:',snapshot.val());
var qrCodesForDoor = snapshot.val();
res.send(qrCodesForDoor); // Send the chosen door as the response
}
});
});
});