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?