Асинхронный вызов запускает aws лямбда дважды - PullRequest
3 голосов
/ 07 января 2020

У меня есть приложение чата, которое, когда я нажимаю кнопку после ввода сообщения, отправляется в мою таблицу DynamoDB. Предполагается, что приложение публикует сообщение один раз, но каким-то образом публикует его дважды.

Конвейер выглядит следующим образом:

Клиент нажимает кнопку send -> попадает в мой API-интерфейс Google Cloud Endpoint -> запускает мою функцию Google Cloud -> вызывает мою AWS лямбда-функцию -> POSTS сообщение DynamoDB.

С помощью SO я изолировал проблему с моей функцией Google Cloud вызывая Lambda асинхронно, который ставит Lambda в очередь дважды.

При использовании asyn c запросы ставятся в очередь перед фактическим выполнением. Поэтому, если вы позвоните один раз, AWS проверит, выполняется ли уже один, а если нет, добавит еще один.

enter image description here ( AWS blog )

В идеале я хотел бы вызывать мою Lambda синхронно, но в соответствии с этим постом Github мне выставили бы счет дважды (?). Он упоминает об увеличении времени ожидания моей функции, но оно уже установлено на 60 секунд - у моей лямбды достаточно времени, чтобы отправить ответ обратно. Есть ли какой-то другой механизм, который ставит мою лямбду в очередь дважды?

Для справки, моя облачная функция Google выглядит следующим образом:

let AWS = require('aws-sdk');

AWS.config.update({
  accessKeyId: ''
  secretAccessKey: ''
  region: ''
})

let lambda = new AWS.Lambda();

exports.helloWorld = async (req,res) =>{
  let payload = {
    pathParameters: req.query.p,
    httpMethod: req.method,
    body: req.method == "POST" ? req.body.message || req.body.user : null,
    cognitoUsername: req.query.u
  }

  let params = {
    FunctionName: '',
    InvocationType: 'RequestResponse',
    Payload: JSON.stringify(payload)
  }

  res.status(200).send( await lambda.invoke(params, function(err,data){
    if (err){throw err}
    else {return data.Payload}
  }).promise())
}

Решение :

На основе решения @ jarmod моя функция Cloud показана ниже. Соответствующая часть находится в конце.

let AWS = require('aws-sdk');

AWS.config.update({
  accessKeyId: ''
  secretAccessKey: ''
  region: ''
})

let lambda = new AWS.Lambda();

exports.helloWorld = async (req,res) =>{
  let payload = {
    pathParameters: req.query.p,
    httpMethod: req.method,
    body: req.method == "POST" ? req.body.message || req.body.user : null,
    cognitoUsername: req.query.u
  }

  let params = {
    FunctionName: '',
    InvocationType: 'RequestResponse',
    Payload: JSON.stringify(payload)
  }

  // code changed only here
  res.status(200).send( await lambda.invoke(params).promise())
}

Редактировать :

@ Ngenator обратил мое внимание на то, что моя функция Google Cloud может запускаться дважды. Для справки, это моя конфигурация API yaml:

swagger: '2.0'
info:
  title: Cloud Endpoints + GCF
  version: 1.0.0
host: service.run.app
x-google-endpoints:
  - name: "service.run.app"
    allowCors: "true"
schemes:
  - https
produces:
  - application/json
paths:
  /function-2:
    get:
      operationId: get 
      parameters:
        - name: p
          in: query
          required: true
          type: string
        - name: u
          in: query
          required: false
          type: string
      x-google-backend:
        address: https://to.my/function-2
      responses:
        '200':
          description: A successful response
          schema:
            type: string
    post:
      operationId: post 
      consumes:
        - application/json
      parameters:
        - name: p
          in: query
          required: true
          type: string
        - name: u
          in: query
          required: false
          type: string
        - in: body
          name: body
          schema:
            type: object
            properties:
              message:
                type: string
              user:
                type: array
                items:
                  type: string
      x-google-backend:
        address: https://to.my/function-2
      responses:
        '200':
          description: A successful response
          schema:
            type: string

1 Ответ

2 голосов
/ 07 января 2020

Ваш звонок на lambda.invoke неверный. Он включает в себя и обратный вызов и ожидает обещание. Вы должны использовать один или другой, предпочтительно последний:

const rc = await lambda.invoke(params).promise();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...