typescript - Deno WebWorker hidas version 1.40 jälkeen
Kehitän web-sovellusta, joka suorittaa monia kyselyjä rinnakkain MySQL:ään. Nopeuttaakseni asioita ja tarjotakseni paremman käyttäjäkokemuksen, käytän web-työntekijöitä tekemään kyselyt. Deno lähettää SQL:n web-työntekijälle, joka suorittaa kyselyn ja palauttaa tuloksen takaisin pää-Deno-lankaan. Tällä tavalla, aina Deno 1.39.4:ään asti, sovellus oli erittäin nopea ja joidenkin kyselyjen suoritusajat laskivat muutamasta sekunnista 0.xx sekuntiin. Kuitenkin, jos päivitän vain Deno 1.40+:ään (kokeilin kaikkia versioita aina 1.46.x asti), kyselyistä tulee erittäin hitaita. Kokeilin myös toisella tietokoneella ja sain saman käyttäytymisen.
Näin alustaan työntekijän ja pyydän kyselyn suorittamista pääsäikeellä:
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 }})
});
}
ja tämä on verkkotyöntekijä:
import { Client } from "https://deno.land/x/[email /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 : []
}
}
Onko sinulla ideoita, mikä sen voisi aiheuttaa?