تايب سكريبت - WebWorker في Deno بطيء منذ الإصدار 1.40


أنا أطور تطبيق ويب يقوم بالعديد من الاستعلامات بالتوازي على MySQL. لتسريع الأمور وتحسين تجربة المستخدم، أستخدم عمال الويب لتنفيذ الاستعلامات. يقوم Deno بإرسال SQL إلى عامل الويب الذي ينفذ الاستعلام ويرسل النتيجة مرة أخرى إلى خيط Deno الرئيسي. بهذه الطريقة، وحتى Deno 1.39.4، كان التطبيق سريعًا جدًا وانخفض وقت تنفيذ بعض الاستعلامات من ثوانٍ إلى 0.xx ثانية. ومع ذلك، إذا قمت بالترقية فقط إلى Deno 1.40+ (جربت جميع الإصدارات حتى 1.46.x)، تصبح الاستعلامات بطيئة جدًا. كما جربت ذلك على جهاز كمبيوتر ثانٍ وحصلت على نفس السلوك.

هكذا أقوم بتهيئة العامل وطلب تنفيذ الاستعلام في الخيط الرئيسي:

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 }})
    });
}

وهذا هو عامل الويب:

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 : []
    }
}

هل لديك أي فكرة عما قد يسببه؟