ken*_*ken 5 amazon-web-services aws-step-functions
我有一个主要用 Javascript 编写的 Lambda 函数的 AWS 步进函数/状态机(虽然一个是用 Java 编写的),我想更好地管理错误处理。
我对捕获错误条件然后转发到流程中的另一个状态没有问题。因此,例如,我的状态机中的以下状态定义将执行传递到NotifyOfError
我能够通过电子邮件和短信适当地发送有关错误状态的状态。
Closure:
Type: Task
Resource: >-
arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:xxx-services-${opt:stage}-transportClosure
Next: WaitForCloudWatch
Catch:
- ErrorEquals:
- "States.ALL"
ResultPath: "$.error-info"
Next: NotifyOfError
Run Code Online (Sandbox Code Playgroud)
但是,我不想将所有错误都交给这个状态,而是我希望以不同的方式处理一些错误。所以起初我认为如果我用给定的“名称”抛出一个 Javascript/Node 错误,那么这个名称将是我可以在ErrorEquals配置中分支的东西。例子:
catch(e) {
if (e.message.indexOf('something') !== -1) {
e.name = "SomethingError";
throw e;
}
Run Code Online (Sandbox Code Playgroud)
但很快意识到这个名字只是被添加到Cause
step-function的部分而不是分支的东西。然后我尝试像这样扩展基本 Error 类:
export default class UndefinedAssignment extends Error {
constructor(e: Error) {
super(e.message);
this.stack = e.stack;
}
}
Run Code Online (Sandbox Code Playgroud)
但是抛出这个错误实际上什么也没做,这意味着当它出现在 Step Function 中时,错误的类型仍然只是“错误”:
"error-info": {
"Error": "Error",
"Cause": "{\"errorMessage\":\"Error: the message",\"errorType\":\"Error\",\"stackTrace\":[\"db.set.catch.e (/var/task/lib/prepWorker/Handler.js:247:23)\",\"process._tickDomainCallback (internal/process/next_tick.js:135:7)\"]}"
}
Run Code Online (Sandbox Code Playgroud)
因此,我仍然不清楚如何区分源自 Node 且可在 step 函数中分支的错误。
注意:对于 Java,它似乎确实正确地拾取了错误类(尽管我在 Java 方面所做的测试要少得多)
以下是我如何让 Step Functions 将自定义错误和消息报告为它的Error
和Cause
。注意我使用的是 Node.js 8.10 Lambda 运行时async
和try/catch
。
exports.handler = async (event) => {
function GenericError(name, message) {
this.name = name;
this.message = message;
}
GenericError.prototype = new Error();
try {
// my implementation which might throw an error
// ...
}
catch (e) {
console.log(e);
let error = new GenericError('CustomError', 'my message');
throw error;
}
};
Run Code Online (Sandbox Code Playgroud)
为简单起见,我忽略了catch(e)
这里的错误对象。stack
如果需要,您也可以将其输入到 GenericError 中。
这个 lambda 函数返回:
{
"errorMessage": "my message",
"errorType": "CustomError",
"stackTrace": [
"exports.handler (/var/task/index.js:33:28)"
]
}
Run Code Online (Sandbox Code Playgroud)
Step Functions 将其转换为:
{
"error": "CustomError",
"cause": {
"errorMessage": "my message",
"errorType": "CustomError",
"stackTrace": [
"exports.handler (/var/task/index.js:33:28)"
]
}
}
Run Code Online (Sandbox Code Playgroud)
在它的LambdaFunctionFailed
事件历史中,并最终将它再次转换为这个状态输出(取决于我们的ResultPath
- 这里没有任何):
{
"Error": "CustomError",
"Cause": "{\"errorMessage\":\"my message\",\"errorType\":\"CustomError\",\"stackTrace\":[\"exports.handler (/var/task/index.js:33:28)\"]}"
}
Run Code Online (Sandbox Code Playgroud)
您应该使用 Lambda 返回抛出的异常callback
。创建 lambda 和状态机的 Cloud Formation 模板示例:
AWSTemplateFormatVersion: 2010-09-09
Description: Stack creating AWS Step Functions state machine and lambda function throwing custom error.
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Handler: "index.handler"
Role: !GetAtt LambdaExecutionRole.Arn
Code:
ZipFile: |
exports.handler = function(event, context, callback) {
function SomethingError(message) {
this.name = "SomethingError";
this.message = message;
}
SomethingError.prototype = new Error();
const error = new SomethingError("something-error");
callback(error);
};
Runtime: "nodejs6.10"
Timeout: 25
StateMachine:
Type: AWS::StepFunctions::StateMachine
Properties:
RoleArn: !GetAtt StatesExecutionRole.Arn
DefinitionString: !Sub
- >
{
"Comment": "State machine for nodejs error handling experiment",
"StartAt": "FirstState",
"States": {
"FirstState": {
"Type": "Task",
"Resource": "${ThrowErrorResource}",
"Next": "Success",
"Catch": [
{
"ErrorEquals": ["SomethingError"],
"ResultPath": "$.error",
"Next": "CatchSomethingError"
}
]
},
"Success": {
"Type": "Pass",
"End": true
},
"CatchSomethingError": {
"Type": "Pass",
"Result": {
"errorHandlerOutput": "Huh, I catched an error"
},
"ResultPath": "$.errorHandler",
"End": true
}
}
}
- ThrowErrorResource: !GetAtt LambdaFunction.Arn
LambdaExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
StatesExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- !Sub states.${AWS::Region}.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: ExecuteLambda
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource: arn:aws:lambda:*:*:function:*
Run Code Online (Sandbox Code Playgroud)
重要部分是 Lambda 函数定义:
exports.handler = function(event, context, callback) {
function SomethingError(message) {
this.name = "SomethingError";
this.message = message;
}
SomethingError.prototype = new Error();
const error = new SomethingError("something-error");
callback(error);
};
Run Code Online (Sandbox Code Playgroud)
具有自定义名称的自定义错误在此处定义。当然你也可以简单地覆盖名称(但我不建议这样做):
exports.handler = function(event, context, callback) {
var e = new Error();
e.name = "SomethingError";
callback(e);
};
Run Code Online (Sandbox Code Playgroud)
像这样返回的错误将被传递到 Step Functions,而不会丢失错误名称。我建议try-catch
在 Lambda 函数中创建一些 top 语句,您可以在其中简单地调用callback
错误。
归档时间: |
|
查看次数: |
6058 次 |
最近记录: |