我如何 运行 代码在操作完成后访问 Apache OpenWhisk 操作的内存中状态?

How do I run code that accesses an Apache OpenWhisk action's in-memory state after the action completes?

我正在测试使用 IBM Cloud Functions(托管 Apache OpenWhisk)在操作完成后在后台 运行 代码,但是我在调​​用 setTimeout 时提供的回调没有 运行 在正确的时间之后,它永远不会 运行 除非我第二次调用该函数。 运行 那时(晚)。

详情:

我想到了两个用例:

我认为这会起作用,因为我使用过其他平台,例如 Google Cloud 运行,我注意到后台有 运行ning 代码(使用 setTimeout 等),看到请求完成后在 Stackdriver 中记录此代码。而且,甚至还有一个由 AWS 开发人员倡导者创建的完整库,它在后台管理 AWS Lambda (https://www.npmjs.com/package/serverless-mysql) 上的 MySQL 个连接。

我测试了以下功能:

// from 
function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

function main() {
    const runId = uuidv4().slice(31, 36);

    console.log(`function started (runId = ${runId})`);

    setTimeout(() => {
        console.log(`after 5s delay (runId = ${runId})`);
    }, 5000);

    return {
        msg: `ok (runId = ${runId})`,
    };
}

我用命令 ibmcloud fn action update logging-in-background src/index.js --kind nodejs:10 部署了它。

我创建了一个 LogDNA 实例并将其设置为我的平台实例,这样我的函数日志就会转到它。这是我在使用命令 ibmcloud fn action invoke logging-in-background --blocking 调用该函数三次后在日志中看到的内容,每次间隔 10 秒(CRN 编辑):

May 18 17:26:23 functions REDACTED 2020-05-18T21:26:23.956013Z    stdout: function started (runId = 9be7c)
May 18 17:26:23 functions REDACTED Activation record '3589870e8ce44cc089870e8ce4acc018' for entity 'logging-in-background'
May 18 17:26:34 functions REDACTED 2020-05-18T21:26:34.111745Z    stdout: after 5s delay (runId = 9be7c)
May 18 17:26:34 functions REDACTED 2020-05-18T21:26:34.115043Z    stdout: function started (runId = faba6)
May 18 17:26:34 functions REDACTED Activation record 'ac47c067177648f187c0671776b8f1c2' for entity 'logging-in-background'
May 18 17:26:44 functions REDACTED 2020-05-18T21:26:44.248470Z    stdout: after 5s delay (runId = faba6)
May 18 17:26:44 functions REDACTED 2020-05-18T21:26:44.253822Z    stdout: function started (runId = 0af34)
May 18 17:26:44 functions REDACTED Activation record 'bbad3eabb3d64ab1ad3eabb3d61ab1a7' for entity 'logging-in-background'

您可以看到当我第一次调用函数时,它只记录了 "function started" 消息。 5 秒后它没有记录 "after 5s delay" 消息。但是,在第二次调用开始时,即第一次调用 10 秒后,它最终记录了与 运行 9be7c 关联的 "after 5s delay" 消息。 setTimeout 的回调似乎永远不会 运行 直到,最早,在下次调用该操作时。

这是 Apache OpenWhisk 设计的工作方式,还是在操作完成后我没有正确地对 运行 后台代码执行某些操作?

您的函数 return 在 setTimeout 完成之前正在运行。

在此处查看文档:

https://github.com/apache/openwhisk/blob/master/docs/actions-nodejs.md#creating-asynchronous-actions

正确的做法:

function main(args) {
    const runId = uuidv4().slice(31, 36);

    console.log(`function started (runId = ${runId})`);
    return new Promise(function(resolve, reject) {
       setTimeout(function() {
         console.log(`after 5s delay (runId = ${runId})`);
         resolve({ msg: `ok (runId = ${runId}) });
       }, 5000);
    })
}

对于 AWS lambda,如果当您将任务留在事件循环中时,该函数不会 return/terminate 请求,直到偶数循环为空。如果您使用特殊的上下文标志来让函数急切地 return,则不能保证后台处理会真正完成。

要初始化连接池并在调用中重用它们,您可以将连接存储在全局变量中并确保它仅被初始化。

另一位用户通过解释 OpenWhisk 不会在操作完成后 运行 在事件循环中编码来帮助我理解发生了什么。因此,不可能做我想做的事,我希望调用每个操作以在操作完成后的某个时间检索存储在局部变量中的数据。