首页 > 解决方案 > Meteor DDP 调用在太长时返回未定义

问题描述

我有两台服务器,一台用于主应用程序,另一台用于大型任务。

User -> Server 1 -> Server 2
Server 1: Main app & Easy tasks
Server 2: Huge Tasks

当我调用需要很长时间才能回答的服务器 2 的函数时,当服务器 2 回答好的结果时,服务器 1 会收到 undefined。但是,如果 server2 的函数响应时间不到 1 分钟,则 server 1 得到 server 2 发送的结果,然后将其发送回客户端。

为什么它只适用于计算时间超过 1 分钟的函数?

客户 :

Meteor.call('reporting.default', params.subReport, params, function(error, result) {
    if (result) self.setState({data: result});
    else self.setState({data: error.message});
});

服务器 1:

Meteor.methods({
    'reporting.default'(subReport, params) {
        this.unblock();
        return Meteor.callWorker('reporting.' + subReport, Meteor.callId(), params).then((result, error) => { if (error) return error; else return result; }).await();
    },
});

Meteor.worker = DDP.connect('localhost:' + Meteor.settings.heavyTasksServer.port);
Meteor.callWorker = (method, ...myParameters) => new Promise((resolve, reject) => {
    console.log(method + ": REQUEST");
    Meteor.worker.call(method, ...myParameters, (err, res) => {
        if (err) {
            console.log(method + ": ERROR");
            reject(err);
        }
        else {
            console.log(method + ": ANSWER");
            resolve(res);
        }
    });
});

Meteor.callId = function () {
    const d =new Date();
    return d.getUTCFullYear() +""+ (d.getUTCMonth()+1) +""+ d.getUTCDate() +""+ d.getUTCHours() +""+ d.getUTCMinutes() +""+ d.getUTCSeconds() +""+ d.getUTCMilliseconds() + "-" + Meteor.userId();
};

服务器 2:

Meteor.methods({
    'reporting.clientsAssets'(callId, params) {
        this.unblock();
        const funcName = "reporting.clientsAssets";
        if (canRunQuery(1, callId, arguments, funcName)) {
            console.log(funcName + ": START");
            const data = reportingClientsAssets(params);
            console.log(funcName + ": END");
            terminateQuery(callId);
            return data;
        }
    }
});

标签: meteorpromisecallbackddp

解决方案


您可以考虑使用异步模型而不是同步模型(可能会超时)。

让我们考虑一种排队机制......创建一个集合调用作业(或任何您喜欢的),服务器 1 在作业集合中创建一条状态为“就绪”的记录。

定时任务(您可以为此使用 node-cron)运行在服务器 2 上,每分钟运行一次,并查找状态为“就绪”的作业。它采用第一个,将状态设置为“正在运行”,然后调用该函数来完成工作。

当该功能完成时,它将任务的状态设置为“完成”。

您利用 Meteor 的反应性,以便用户可以看到作业的状态,一旦启动,它就会移动到“正在运行”,然后在完成后移动到“完成”。此时可能会出现一个链接,以便他们可以访问数据、报告或生成的任何内容。

这种机制没有超时问题,并且很好地解耦。


推荐阅读