我使用AWS Step Functions
并具有以下工作流程
initStep -这是一个lambda函数处理程序,它获取一些数据并将其发送到SQS
进行外部服务。
activity = os.getenv('ACTIVITY')
queue_name = os.getenv('QUEUE_NAME')
def lambda_handler(event, context):
event['my_activity'] = activity
data = json.dumps(event)
# Retrieving a queue by its name
sqs = boto3.resource('sqs')
queue = sqs.get_queue_by_name(QueueName=queue_name)
queue.send_message(MessageBody=data, MessageGroupId='messageGroup1' + str(datetime.time(datetime.now())))
return event
validationWaiting -这是一个activity
,正在等待来自包含数据的外部服务的答复。
完成-这是一个lambda函数处理程序,它使用initStep
中的数据。
def lambda_handler(event, context):
email = event['email'] if 'email' in event else None
data = event['data'] if 'data' in event else None
client = boto3.client(service_name='ses')
to = email.split(', ')
message_conrainer = {'Subject': {'Data': 'Email from step functions'},
'Body': {'Html': {
'Charset': "UTF-8",
'Data': """<html><body>
<p>""" + data """</p>
</body> </html> """
}}}
destination = {'ToAddresses': to,
'CcAddresses': [],
'BccAddresses': []}
return client.send_email(Source=from_addresses,
Destination=destination,
Message=message_container)
它确实可以工作,但是问题是我正在将完整数据从initStep
发送到外部服务,只是稍后再传递给complete
。可能会添加更多步骤。
我认为最好将其共享为某种(当前步骤功能的)全局数据,那样我可以添加或删除步骤,并且所有数据仍然可用。
答案 0 :(得分:1)
您可以使用InputPath
和ResultPath
。在initStep
中,您只会将必要的数据发送到外部服务(可能与执行的某些唯一标识符一起)。在ValidaitonWaiting
步骤中,您可以设置以下属性(在状态机定义中):
InputPath
:什么数据将提供给GetActivityTask
。可能您想将其设置为类似$.execution_unique_id
的地方,其中execution_unique_id
是数据中的字段,外部服务用来标识执行(以在initStep
期间与特定请求进行匹配)。ResultPath
:ValidationWaiting活动的输出将保存在数据中的位置。您可以将其设置为$.validation_output
,然后将显示来自外部服务的json结果。通过这种方式,您可以只向外部服务发送实际需要的数据,并且不会失去对输入中先前(在ValidationWaiting
步骤之前)的任何数据的访问权限。
例如,您可以对状态机进行以下定义:
{
"StartAt": "initStep",
"States": {
"initStep": {
"Type": "Pass",
"Result": {
"executionId": "some:special:id",
"data": {},
"someOtherData": {"value": "key"}
},
"Next": "ValidationWaiting"
},
"ValidationWaiting": {
"Type": "Pass",
"InputPath": "$.executionId",
"ResultPath": "$.validationOutput",
"Result": {
"validationMessages": ["a", "b"]
},
"Next": "Complete"
},
"Complete": {
"Type": "Pass",
"End": true
}
}
}
我为Pass
和initStep
使用了ValidationWaiting
状态来简化示例(我没有运行它,但是它应该可以工作)。 Result
字段专用于Pass
任务,它等同于Lambda函数或活动的结果。
在这种情况下,Complete
步骤将获得以下输入:
{
"executionId": "some:special:id",
"data": {},
"someOtherData": {"value": key"},
"validationOutput": {
"validationMessages": ["a", "b"]
}
}
因此,ValidationWaiting
步骤的结果已保存到validationOutput
字段中。
答案 1 :(得分:1)
这里是使用InputPath和ResultPath的简短解决方案。我的Lambda Check_Ubuntu_Updates返回准备更新的实例列表。实例列表由步骤Notify_Results接收,然后使用此数据。请记住,如果您的Step Function中有多个ResultPath,并且在一个步骤中需要多个输入,则只能将InputPath与$一起使用。
{
"Comment": "A state machine that check some updates systems available.",
"StartAt": "Check_Ubuntu_Updates",
"States": {
"Check_Ubuntu_Updates": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:#############:function:Check_Ubuntu_Updates",
"ResultPath": "$.instances",
"Next": "Notify_Results"
},
"Notify_Results": {
"Type": "Task",
"InputPath": "$.instances",
"Resource": "arn:aws:lambda:us-east-1:#############:function:Notify_Results",
"End": true
}
}
}
答案 2 :(得分:1)
根据Marcin Sucharski的答案,我想出了自己的解决方案。
我需要使用Type: Task
,因为initStep
是发送SQS的lambda。
我在InputPath
中不需要ValidationWaiting
,而只需要ResultPath
来存储活动中收到的数据。
我使用Serverless框架,这是我的最终解决方案:
StartAt: initStep
States:
initStep:
Type: Task
Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:init-step
Next: ValidationWaiting
ValidationWaiting:
Type: Task
ResultPath: $.validationOutput
Resource: arn:aws:states:#{AWS::Region}:#{AWS::AccountId}:activity:validationActivity
Next: Complete
Catch:
- ErrorEquals:
- States.ALL
ResultPath: $.validationOutput
Next: Complete
Complete:
Type: Task
Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:complete-step
End: true