AWS lambda 实例在 xstate 调用承诺时关闭

Posted

技术标签:

【中文标题】AWS lambda 实例在 xstate 调用承诺时关闭【英文标题】:AWS lambda instance shuts down while xstate invoke promise 【发布时间】:2020-06-20 00:58:27 【问题描述】:

我有一个 lambda 函数,它使用 xstate 顺序执行某些任务,其中一个步骤是将数据保存到 dynamo db。但是我的 lambda 在执行以下行时立即结束执行。

const response = await new DynamoDB.DocumentClient().put(params).promise();

我的代码:

import Handler from "aws-lambda";
import interpret from 'xstate';
import  Machine from "xstate";
import PutItemInput from "aws-sdk/clients/dynamodb";
import DynamoDB from "aws-sdk";

export const recordProcessor: Handler = async (event) => 
  console.log('records size----->', event.Records.length);
  for (const record of event.Records) 
      const body = JSON.parse(record.body);
      console.log('body ----->', body);

    interpret(Machine(id:'test',
      context:body,
      initial: 'start',
      states:
        start: 
          invoke: 
            src: context => initiate(context),
            onDone: 
              target: 'success'
            
          
        ,
        success: 
          type: 'final'
        
      
    )).onTransition(state => 
      if (state.changed) 
        console.log('state ----> ', state.value);
      
    ).onDone(() => console.log('done--->')).start();
  


  async function initiate(context: any) 
    console.log('DbDynamoImpl ::: insert ::: start :::');
    let params: PutItemInput = 
      TableName: 'test',
      Item: context
    ;
    try 
      const response = await new DynamoDB.DocumentClient().put(params).promise();
      console.log('DbDynamoImpl ::: insert ::: response :::', response);
      return true;
     catch (e) 
      console.log("DynamoDb insert error", e);
      return false;
    
  

;

【问题讨论】:

不看完整代码很难说。 添加了测试代码,因为我无法分享我的整个代码。 由于项目时间表的原因,我不得不将实现从 xstate 更改为责任链设计模式,并且还没有时间让 Greg 和 Iko 进行检查。但是会尽快检查并更新...如果可行,其他人也可以免费投票。 【参考方案1】:

async 添加到您的函数中,然后再次测试。

exports.handler = async (event, context) => 
    return ...

【讨论】:

我认为您需要为任何异步函数调用添加await。我的意思是initiate【参考方案2】:

您在点击return 语句之前解决了 Promise。您可以尝试resolve Promise 使用您需要返回的值吗?然后它将使用这些值转到 onDone 块。还有trycatch块在这里是多余的,因为xstate中的service会自动为你处理。

只需在服务调用语句中返回承诺,因为它需要是一个返回Promise的函数

function initiate(context: any) 
  console.log('DbDynamoImpl ::: insert ::: start :::');
  let params: PutItemInput = 
    TableName: 'test',
    Item: context,
  ;
  return new DynamoDB.DocumentClient().put(params).promise();

然后在你的onDone 块中你可以console.log('DbDynamoImpl ::: insert ::: response :::', response);

onDone: 
  target: 'success',
  actions: (ctx, e) => console.log('DbDynamoImpl ::: insert ::: response :::', e),

【讨论】:

【参考方案3】:

将机器解释和交互包装成一个 Promise 允许您等待状态机达到最终状态。

大概是这样的


export const recordProcessor: Handler = async (event) => 
  console.log('records size----->', event.Records.length);
  for (const record of event.Records) 
      const body = JSON.parse(record.body);
      console.log('body ----->', body);
      await setupMachine(...);
...


function setupMachine(...)
  return new Promise((resolve, reject) => 
    interpret(Machine(id:'test',
      context:body,
      initial: 'start',
      states:
        start: 
          invoke: 
            src: context => initiate(context),
            onDone: 
              target: 'success'
            
          
        ,
        success: 
          type: 'final'
        
      
    )).onTransition(state => 
      if (state.changed) 
        console.log('state ----> ', state.value);
      
    )
     .onDone(() =>  console.log('done--->'); return resolve())
     .onStop(() => reject());
     .start();
   
  );

【讨论】:

以上是关于AWS lambda 实例在 xstate 调用承诺时关闭的主要内容,如果未能解决你的问题,请参考以下文章

如何从我的 EC2 实例调用 AWS Lambda 函数?

我可以限制 AWS Lambda 的并发调用吗?

AWS Lambda 无法连接到 RDS 实例,但我可以在本地连接?

AWS Lambda 函数能否通过 *** 调用终端节点?

如何使用AWS Lambda函数在本地系统上执行文件

AWS Lambda + NAT 网关的替代方案