I’m developing a webapp witch does many queries in parallel to mySLQ.
To speed things up and have a better user experience, I’m using webworkers to make the queries. Deno send the SQL to the webworker which excetutes the query end posts result back to the main Deno thread.
In this way, until Deno 1.39.4, the application was very fast and some queries execution time dropped down from some sedonds to 0.xx seconds.
However if I just upgrade to Deono 1.40+ (tried all versions up to 1.46.x), the queries become very slow.
I also tried on a second computer and I got the same behaviour.
This is how I initialize worker and request the query executiuon on main thread:
connect(): Promise<this> {
return new Promise(resolve => {
this.worker = new Worker(import.meta.resolve("./MySQLWorker.ts"), { type: "module" });
this.worker.addEventListener("message", e => resolve(this), { once: true });
this.worker.postMessage({ msg: "connect", data: this.settings });
});
}
query(sql:string, values?:any[]):Promise<any>{
return new Promise(resolve => {
const requestId = crypto.randomUUID();
const listener = (e:any) => {
const message = e.data;
if (message.requestId != requestId) return;
this.worker?.removeEventListener("message", listener);
resolve(message.data);
}
this.worker?.addEventListener("message", listener);
this.worker?.postMessage({ requestId, msg: "query", data: { sql, values }})
});
}
and this is the webworker
import { Client } from "https://deno.land/x/[email protected]/mod.ts";
const client = new Client();
let iid = 0;
addEventListener("message", async e => {
const message = e.data;
switch(message.msg){
case "connect": {
await client.connect(message.data);
postMessage("connected");
iid = setInterval(() => query("SELECT id FROM users WHERE id = 0"), 60000); // keep connection alive
break;
}
case "disconnect": {
clearInterval(iid);
client.close();
break;
}
case "query": {
const requestId = message.requestId;
setTimeout(async () => {
/* Sometimes in production / test under customer infrastructure
* the connection is forcibly closed by the remote host. (os error 10054)
* That causes the application to crash. So we try to catch this error
* and exceute the query again for a maxAttempts number of times before failing
* but keeping the application alive anyways
*/
const sql = message.data.sql;
const values = message.data.values;
let maxAttempts = 5;
let data = undefined;
while (data == undefined && maxAttempts-- > 0){
data = await query(sql, values);
if (data == undefined && maxAttempts > 0) {
console.log("DB Connection problem, trying again in 500ms");
await pause(500);
}
}
data = data || [];
postMessage({ requestId, data });
}, 1)
break;
}
}
});
function pause(millis:number):Promise<void>{
return new Promise(resolve => setTimeout(resolve, millis));
}
// deno-lint-ignore no-explicit-any
async function query(sql: string, values?:any):Promise<any>{
try {
return await client.query(sql, values);
} catch (err){
return err.code == "ECONNRESET" ? undefined : []
}
}
any idea?