I am designing an ticket system using NodeJS and Mysql-Promise.
For safety and consistency, I want to use Transaction but I worry about the deadlock.
The scenario is
People can buy multi tickets in one order
I would check every tickets whether the rest amount of tickets is enough or not.
I update the amount of tickets
I create the order
The code is
await ctx.conn.beginTransaction()
// check amount of tickets
let ticketIdList = ctx.body.tickets.map(t => t._id)
let ticketList = await models.ticket.findTicketList(ctx.conn, ticketIdList)
for (let t in ticketList) {
let ticketBook = ctx.body.tickets.filter(tB => tB._id === t._id)
if (t.perMinSaleCount > ticketBook.count || t.perMaxSaleCount < ticketBook.count) {
ctx.stats = 400
return ctx.body = {
error: "FailTickets"
}
}
if (t.sold + ticketBook.count > t.total) {
ctx.stats = 400
return ctx.body = {
error: "SoldOut"
}
}
}
// update the tickets
await Promise.all(
ctx.body.tickets.map(t => models.ticket.reserveTicket(ctx.conn, t._id, t.count))
)
// create Order
await model.order.createOrder(...)
await ctx.conn.commit()
My big concern is the ctx.conn is create by pool
mysql.createPool({
......
})
Would // await Promise.all(ctx.body.tickets.map(t => models.ticket.reserveTicket(ctx.conn, t._id, t.count))) this lines make sql in multi connections and cause deadlock ?
How to properly use conn.beginTransaction()?
Thanks
Related
I am developing a middleware using express.js with mysql(new to mysql) and in my situation I have built this patch method to update the table. but the issue is I dont want to pass the entire field set to update specific fields out of many. so whats the preferred way to do this so that whatever fields I will send in request body those fields should be updated only.
const updateCompany = (req, res, next) => {
const cid = req.params.cid;
const {
company_id,
company_name,
company_address_line1,
company_address_line2,
company_email,
company_phone,
longitude,
latitude
} = req.body;
var myquery = `UPDATE Company_Master SET company_name="${company_name}",company_address_line1="${company_address_line1}",company_address_line2="${company_address_line2}",company_email="${company_email}",company_phone="${company_phone}",longitude=${longitude},latitude=${latitude} WHERE company_id = "${cid}"`
conn.query(myquery, (err, result) => {
if (err) {
console.log("err" + err);
} else {
res.status(201).json(req.body);
}
})
}
You can do as follows
const updateCompany = (req, res, next) => {
const cid = req.params.cid;
let
allowedcolumns = ["company_name", "company_address_line1", ... ], //all columns that can be updated
stmts = [],
values = [];
for (let c of allowedcolumns) {
if (c in req.body) { //check if there is a value for that column in the request body
stmts.push(`${c} = ?`),
values.push(req.body[c]);
}
}
if (stmts.length == 0) {
return res.sendStatus(204); //nothing to do
}
values.push(cid);
conn.query(`UPDATE Company_Master SET ${stmts.join(", ")} WHERE company_id = ?`, values, (err, result) => {
if (err) {
console.log("err" + err);
res.sendStatus(400);
} else {
res.status(200).json(req.body);
}
})
}
allowedcolumns will contain all columns that you are allowed to update via this request. For each of them check, whether there is a value in the request body or not. If yes, add it to the update statements, if not, ignore it (this assumes, the properties in the req.body and the columns in the table have the same name). Furthermore, to create a parameterized query, add the respective value to a values array, that you then can pass to the query.
If you don't have any values, there is nothing to do, so you can immediately return.
Else execute the query (don't forget to also add the cid to the values array). And return the respective status, based on whether there was an error or not.
BTW: 201 is status CREATED. You shouldn use that, if you are updating an already existing entity ...
I am trying to monitor CPU utilization with puppeteer. I can find handful relate solutions for page loading measurement and heap measuring but nothing to see the CPU utilization during the life of a page not only when the page is loading.
The same information is available in chrome under dev-tools/Performance monitor as
"CPU usage"
Dug through the code and figured I would share since it doesn't seem like this explanation has surfaced anywhere.
It looks like the relevant code in devtools is here:
https://source.chromium.org/chromium/chromium/src/+/main:out/Debug/gen/third_party/devtools-frontend/src/front_end/core/sdk/PerformanceMetricsModel.js;l=43?q=requestMetrics&ss=chromium%2Fchromium%2Fsrc
case "CumulativeTime" /* CumulativeTime */:
value = (data.lastTimestamp && data.lastValue) ?
Platform.NumberUtilities.clamp((metric.value - data.lastValue) * 1000 / (timestamp - data.lastTimestamp), 0, 1) :
0;
data.lastValue = metric.value;
data.lastTimestamp = timestamp;
break;
Devtools is polling for metrics, which appear to contain the cumulative time spent on a task since the metrics were enabled. CPU usage is the percent of time taken by all tasks since the last metrics request.
Sample code to log CPU usage over time:
interface CPUUsageSnapshot {
timestamp: number,
usage: number,
}
export interface CPUStats {
average: number,
snapshots: CPUUsageSnapshot[]
}
function processMetrics(metrics: GetMetricsResponse): {
timestamp: number,
activeTime: number
} {
const activeTime = metrics.metrics.filter(m => m.name.includes("Duration")).map(m => m.value).reduce((a, b) => a + b)
return {
timestamp: metrics.metrics.find(m => m.name === "Timestamp")?.value || 0,
activeTime
}
}
async function logMetrics(cdp: CDPSession, interval: number): Promise<() => Promise<CPUStats>> {
await cdp.send("Performance.enable", {
timeDomain: "timeTicks"
})
const { timestamp: startTime, activeTime: initialActiveTime } = processMetrics(await cdp.send("Performance.getMetrics"))
const snapshots: CPUUsageSnapshot[] = []
let cumulativeActiveTime = initialActiveTime
let lastTimestamp = startTime
const timer = setInterval(async () => {
const {timestamp, activeTime} = processMetrics(await cdp.send("Performance.getMetrics"))
const frameDuration = timestamp - lastTimestamp
let usage = (activeTime - cumulativeActiveTime) / frameDuration
cumulativeActiveTime = activeTime
if (usage > 1) usage = 1
snapshots.push({
timestamp,
usage
})
lastTimestamp = timestamp
}, interval)
return async () => {
clearInterval(timer)
await cdp.send("Performance.disable")
return {
average: cumulativeActiveTime / (lastTimestamp - startTime),
snapshots
}
}
}
so I am working on a command that makes like a vote embed, and it doesn't really work. when I use (in my case) $repvote #user it doesn't recognize the user or anything.., let me know for any solutions!
if (message.author.bot) return;
if (message.content.startsWith(prefix + "repvote")) {
if (!message.member.hasPermission("MANAGE_ROLES")) return message.channel.send('You do not have that permission! :x:').then(message.react('❌'));
let repUser = message.mentions.members.first()
if(!repUser) return message.channel.send("Please mention the user you want to setup the vote for!").then(message.react('❌')).then(msg => { msg.delete({ timeout: 5000 });
const repVoteEmbed = new Discord.MessageEmbed()
repVoteEmbed.setTitle("Vote for Representative Members :crown:")
repVoteEmbed.setDescription(`User ${repUser} wants to recieve Representative Members :crown: role! Do you agree?`)
repVoteEmbed.setFooter(`Vote by: ${message.author.tag}, started on : ${message.createdAt}`)
message.channel.send({repVoteEmbed}).then(message.react('✔')).then(message.react('❌'))
})
}})```
You missing message.channel.send(embed).then(msg =>....
Message channel send return a promise of the sent message, so you need use it to react
const Discord = require('discord.js');
const bot = new Discord.Client();
bot.on('message', async (message) => {
if (message.author.bot) return;
if (message.content.startsWith(prefix + 'repvote')) {
if (!message.member.hasPermission('MANAGE_ROLES')) return message.channel.send('You do not have that permission! :x:').then(message.react('❌'));
let repUser = message.mentions.members.first();
if (!repUser) {
message.channel.send('Please mention the user you want to setup the vote for!').then((declineMsg) => {
message.react('❌');
declineMsg.delete({
timeout: 5000,
});
});
return;
}
const repVoteEmbed = new Discord.MessageEmbed();
repVoteEmbed.setTitle('Vote for Representative Members :crown:');
repVoteEmbed.setDescription(`User ${repUser} wants to recieve Representative Members :crown: role! Do you agree?`);
repVoteEmbed.setFooter(`Vote by: ${message.author.tag}, started on : ${message.createdAt}`);
message.channel.send(repVoteEmbed).then((msg) => {
msg.react(`✔`).then(() => msg.react('❌'));
});
}
});
I just confuse with this case. I've been try to make sure the time zone in MySql and see the data that out from Date(Date.now()). That's all is correct with my timezone. But when i try to input the data to MySql, and i check in my Database. The time zone is wrong and different with my Time zone. Is there anyone can help me ?
This my code
const Employee = require('../models/employee');
const History = require('../models/history');
async createHistory(employee){
let result;
try {
const checkData = await Employee.findOne({where :
{employeeId : employee.employeeId}
});
if(checkData !== null){
const createData = await History.create({
employeeId : employee.employeeId,
in : Date(Date.now())
});
console.log(date.toLocaleString());
console.log('True')
}else {
result = {message : false}
}
} catch (e) {
logEvent.emit('APP_ERROR',{
logTitle: '[CREATE-HISTORY-ERROR]',
logMessage: e
});
}
return result;
}
The Time in field 'in' is wrong, it should be 14:43
I just get the answer,
The answer is .. because i using Sequelize to store the data to MySql i have to input the time zone in my connection.
Here my code :
const connection = new Sequelize(
{
timezone: "+07:00"
}
);
I am trying to load data from data service but ID appears as type error
selectedModule(item: any) {
this.module = item;
console.log(this.module);
this.dataService.getAny('/modules/get-by-module', "Id", '1')
.then((module: IModuleBySector) => {
const cust = JSON.stringify(module);
this.moduleSelected = module;
console.log(this.moduleSelected);
});
}
I believe you want to send ID to the server side code and want to get data whose ID=1. You should try this,
selectedModule(item: any) {
this.module = item;
console.log(this.module);
this.dataService.getAny('/modules/get-by-module?Id=1')
.then((module: IModuleBySector) => {
const cust = JSON.stringify(module);
this.moduleSelected = module;
console.log(this.moduleSelected);
});
}