Escribí una aplicación web para hacer reservas para un concierto. Las personas pueden seleccionar a partir de ciertas fechas y pueden elegir con cuántas personas vienen seleccionando una cantidad de asientos.
Utilizo una hoja de cálculo para recopilar todas las reservas. Anoté las últimas 2 funciones del proceso. Si presiono el botón para ordenar los asientos, se activan 2 funciones: validar() en el frontend y getLastCheck() en el backend. Esta es una última verificación de si las cantidades solicitadas de asientos todavía están disponibles. Si es así, los datos se escriben en la hoja de cálculo.
Probé el guión varias veces con otros 4 colegas y simultáneamente intentamos reservar 3 asientos en la misma fecha. Como solo quedaban 10 asientos, 2 de nosotros deberíamos recibir el mensaje de que "los asientos no están reservados". A veces funcionaba bien, otras veces solo 1 de nosotros recibía el mensaje "los asientos no están reservados" y las otras 4 personas (¡1 de más!) podían reservar sus asientos. En ese caso superamos el aforo máximo.
Supongo que la actualización tardía de la hoja de cálculo (que da como resultado una evaluación incorrecta) se debe al tiempo de tráfico desde y hacia la hoja de cálculo. ¿Hay alguna manera de resolver esta evaluación incorrecta al enviar los datos simultáneamente?
Función de interfaz:
function validate() { var info = {}; info.firstName = document.getElementById("first-name").value; info.lastName = document.getElementById("last-name").value; info.mail = document.getElementById("email").value.trim(); info.date = document.getElementById("select-date").value; info.seats = document.getElementById("select-seats").value; google.script.run.withSuccessHandler(function(result){ console.log(result); }).getLastCheck(info); }función de fondo:
function getLastCheck(info) { var listAll = wsRsrv.getRange(2, 5, lastRowRsrv, 2).getValues(); var dates = listAll.map(function(element){ return element[0]; }); var seats = listAll.map(function(element){ return element[1]; }); var sum = 0; var diff = maxPerDate - info.seats; for (var i = 0; i<listAll.length; i++) { if (info.date == dates[i]) { sum += Number(seats[i]); } } if (sum <= diff) { wsRsrv.appendRow([new Date(), info.lastName, info.firstName, info.mail, info.date, info.seats]); return "seats are booked"; } else { return "seats are not booked"; } }Lo probé y parece que funciona bien.
function lockedFunction() { var active_spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); // BEGIN - start lock here const lock = LockService.getScriptLock(); try { lock.waitLock(5000); // wait 5 seconds for others' use of the code section and lock to stop and then proceed } catch (e) { console.log('Could not obtain lock after 5 seconds.'); return "Error: Server busy try again later... Sorry :(" } // note: if return is run in the catch block above the following will not run as the function will be exited const active_sheet = active_spreadsheet.getActiveSheet() const new_start_row = active_sheet.getLastRow() + 1; // Run the function const data = { firstName: 'David', lastName: 'Salomon', mail: 'mail@example.com', date: new Date(), seats: 10 } getLastCheck(data) SpreadsheetApp.flush(); // applies all pending spreadsheet changes lock.releaseLock(); // END - end lock here return; }Puede consultar este otro hilo para tener más ideas sobre cómo implementarlo, pero como se menciona en los comentarios, puede consultar la documentación de Google.