update
This commit is contained in:
@ -393,153 +393,143 @@ class GpsTracksModels {
|
|||||||
|
|
||||||
static bundleCreate2(logs = {}, rltm = {}) {
|
static bundleCreate2(logs = {}, rltm = {}) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
let lock = null;
|
let lock = null
|
||||||
let trackLock = null; // Scope dipindah ke atas agar bisa di-unlock di akhir
|
|
||||||
let conn = null; // Scope dipindah ke atas agar bisa di-rollback
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
conn = await MysqlHelpers.createConnection();
|
const conn = await MysqlHelpers.createConnection()
|
||||||
await MysqlHelpers.createTrx(conn);
|
await MysqlHelpers.createTrx(conn)
|
||||||
|
|
||||||
let rltmLength = Object.keys(rltm).length;
|
let rltmLength = Object.keys(rltm).length
|
||||||
let resLogs = undefined;
|
let resLogs = undefined
|
||||||
|
|
||||||
if (Object.keys(logs).length > 0) {
|
if (Object.keys(logs).length > 0) {
|
||||||
resLogs = await MysqlHelpers.queryTrx(
|
resLogs = await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`INSERT INTO t_gps_tracks SET ?;`,
|
`INSERT INTO t_gps_tracks SET ?;`,
|
||||||
[logs]
|
[logs],
|
||||||
);
|
)
|
||||||
|
|
||||||
if (logs.action == "location") {
|
let trackLock = null
|
||||||
// Lock 1: Track Insert
|
|
||||||
trackLock = await rltmMutex.lock(
|
|
||||||
`tracks_insert:${logs.device_id}`,
|
|
||||||
{
|
|
||||||
duration: 9000, // Diubah menjadi 9 detik (9000 ms)
|
|
||||||
maxWait: 9000,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const date = logs.crt_d;
|
try {
|
||||||
const mm = moment.unix(date).format("MM");
|
if (logs.action == "location") {
|
||||||
const yy = moment.unix(date).format("YY");
|
|
||||||
|
|
||||||
logs.id = resLogs.insertId;
|
trackLock = await rltmMutex.lock(
|
||||||
|
`tracks_insert:${logs.device_id}`,
|
||||||
|
{
|
||||||
|
duration: 90000,
|
||||||
|
maxWait: 90000,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
await MysqlHelpers.queryTrx(
|
const date = logs.crt_d
|
||||||
conn,
|
const mm = moment.unix(date).format("MM")
|
||||||
`INSERT INTO tracks_${yy}${mm} SET ?`,
|
const yy = moment.unix(date).format("YY")
|
||||||
[logs]
|
|
||||||
);
|
logs.id = resLogs.insertId
|
||||||
|
|
||||||
|
await MysqlHelpers.queryTrx(
|
||||||
|
conn,
|
||||||
|
`
|
||||||
|
INSERT INTO tracks_${yy}${mm}
|
||||||
|
SET ?
|
||||||
|
`,
|
||||||
|
[logs]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (trackLock) {
|
||||||
|
await rltmMutex.unlock(trackLock)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// HAPUS blok finally di sini. trackLock WAJIB ditahan sampai COMMIT selesai.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rltmLength > 0 && typeof resLogs !== "undefined") {
|
if (rltmLength > 0 && typeof resLogs !== "undefined")
|
||||||
rltm.master_id = resLogs.insertId;
|
rltm.master_id = resLogs.insertId
|
||||||
}
|
|
||||||
|
|
||||||
if (rltmLength > 0 && rltm.latitude !== null && rltm.longitude !== null) {
|
if (
|
||||||
// Lock 2: Realtime Update
|
rltmLength > 0 &&
|
||||||
|
rltm.latitude !== null &&
|
||||||
|
rltm.longitude !== null
|
||||||
|
) {
|
||||||
|
// === KUNCI DI SINI ===
|
||||||
|
// Lock per device_id supaya SELECT-DELETE-INSERT untuk
|
||||||
|
// device yang sama tidak berjalan bersamaan dari request/worker
|
||||||
|
// lain. Inilah yang tadinya memicu ER_DUP_ENTRY dan
|
||||||
|
// "Lock wait timeout" karena banyak transaksi menumpuk
|
||||||
|
// menunggu baris yang sama.
|
||||||
lock = await rltmMutex.lock(`t_gps_tracks_rltm:${rltm.device_id}`, {
|
lock = await rltmMutex.lock(`t_gps_tracks_rltm:${rltm.device_id}`, {
|
||||||
duration: 9000, // Diubah menjadi 9 detik (9000 ms)
|
duration: 90000, // maksimal lock dipegang 5 detik
|
||||||
maxWait: 9000,
|
maxWait: 90000, // menunggu lock maksimal 10 detik lalu error
|
||||||
});
|
})
|
||||||
|
|
||||||
let devices = await MysqlHelpers.queryTrx(
|
let devices = await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`SELECT id FROM t_gps_tracks_rltm WHERE device_id = ?`,
|
`SELECT id FROM t_gps_tracks_rltm as rltm WHERE rltm.device_id = ?`,
|
||||||
[rltm.device_id]
|
[rltm.device_id],
|
||||||
);
|
)
|
||||||
if (devices.length > 1) {
|
if (devices.length > 1)
|
||||||
await MysqlHelpers.queryTrx(
|
await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`DELETE FROM t_gps_tracks_rltm WHERE device_id = ?;`,
|
`DELETE from t_gps_tracks_rltm WHERE device_id = ?;`,
|
||||||
[rltm.device_id]
|
[rltm.device_id],
|
||||||
);
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (rltm.vhc_id != 0) {
|
if (rltm.vhc_id != 0) {
|
||||||
let vhcs = await MysqlHelpers.queryTrx(
|
let vhcs = await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`SELECT id FROM t_gps_tracks_rltm WHERE vhc_id = ?`,
|
`SELECT id FROM t_gps_tracks_rltm as rltm WHERE rltm.vhc_id = ?`,
|
||||||
[rltm.vhc_id]
|
[rltm.vhc_id],
|
||||||
);
|
)
|
||||||
if (vhcs.length > 1) {
|
if (vhcs.length > 1)
|
||||||
await MysqlHelpers.queryTrx(
|
await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`DELETE FROM t_gps_tracks_rltm WHERE vhc_id = ?;`,
|
`DELETE from t_gps_tracks_rltm WHERE vhc_id = ?;`,
|
||||||
[rltm.vhc_id]
|
[rltm.vhc_id],
|
||||||
);
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rltm.drv_id != 0) {
|
if (rltm.drv_id != 0) {
|
||||||
let drvs = await MysqlHelpers.queryTrx(
|
let drvs = await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`SELECT id FROM t_gps_tracks_rltm WHERE drv_id = ?`,
|
`SELECT id FROM t_gps_tracks_rltm as rltm WHERE rltm.drv_id = ?`,
|
||||||
[rltm.drv_id]
|
[rltm.drv_id],
|
||||||
);
|
)
|
||||||
if (drvs.length > 1) {
|
if (drvs.length > 1)
|
||||||
await MysqlHelpers.queryTrx(
|
await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`DELETE FROM t_gps_tracks_rltm WHERE drv_id = ?;`,
|
`DELETE from t_gps_tracks_rltm WHERE drv_id = ?;`,
|
||||||
[rltm.drv_id]
|
[rltm.drv_id],
|
||||||
);
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await MysqlHelpers.queryTrx(
|
await MysqlHelpers.queryTrx(
|
||||||
conn,
|
conn,
|
||||||
`INSERT INTO t_gps_tracks_rltm SET ? ON DUPLICATE KEY UPDATE ?;`,
|
`INSERT INTO t_gps_tracks_rltm SET ? ON DUPLICATE KEY UPDATE ?;`,
|
||||||
[rltm, rltm]
|
[rltm, rltm],
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eksekusi Commit SEBELUM melepaskan Mutex
|
await MysqlHelpers.commit(conn)
|
||||||
await MysqlHelpers.commit(conn);
|
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
type: "success",
|
type: "success",
|
||||||
result: resLogs,
|
result: resLogs,
|
||||||
});
|
})
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("ERROR bundleCreate2 : " + (rltm.device_id || "unknown"));
|
console.log("ERROR bundleCreate2 : " + rltm.device_id)
|
||||||
|
reject(err)
|
||||||
// WAJIB ROLLBACK JIKA ERROR! (Jika tidak, koneksi menggantung & menyebabkan Lock Wait Timeout)
|
|
||||||
if (conn) {
|
|
||||||
try {
|
|
||||||
await MysqlHelpers.rollback(conn);
|
|
||||||
} catch (rollbackErr) {
|
|
||||||
console.log("ERROR Rollback : ", rollbackErr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reject(err);
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
// MUTEX HANYA BOLEH DILEPAS SETELAH COMMIT / ROLLBACK SELESAI
|
// Lock selalu dilepas, baik sukses maupun gagal,
|
||||||
if (trackLock) {
|
// supaya tidak deadlock request device yang sama berikutnya.
|
||||||
try {
|
|
||||||
await rltmMutex.unlock(trackLock);
|
|
||||||
} catch (unlockErr) {
|
|
||||||
console.log("ERROR unlock trackLock : " + logs.device_id, unlockErr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lock) {
|
if (lock) {
|
||||||
try {
|
try {
|
||||||
await rltmMutex.unlock(lock);
|
await rltmMutex.unlock(lock)
|
||||||
} catch (unlockErr) {
|
} catch (unlockErr) {
|
||||||
console.log("ERROR unlock lock : " + rltm.device_id, unlockErr);
|
console.log("ERROR unlock mutex : " + rltm.device_id, unlockErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catatan: Jika MysqlHelpers tidak otomatis melepas (release) koneksi
|
|
||||||
// ke pool setelah commit/rollback, pastikan Anda menambahkannya di sini.
|
|
||||||
// if (conn && typeof conn.release === 'function') conn.release();
|
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async get2() {
|
static async get2() {
|
||||||
|
|||||||
Reference in New Issue
Block a user