hardyscc/aws-nestjs-starter

Invoke graphql lambda from another lambda

epiphaneSpecter opened this issue · 8 comments

I have two lambda (separate project) developed in nestjs + grapqh. I am trying to call one of the lambda through the other and get responses with the invoke function of aws sdk.

Did the problem come from my way of writing the payload? because I have tried several formats but still no result.
because I noticed that the request is well received by the second lambda, but it may not be able to resolve it.

Tks in advance for your feedback

let lambda = new Lambda({
            apiVersion: '2015-03-31',
            endpoint: process.env.IS_DDB_LOCAL === 'true'
              ? 'http://localhost:3002'
              : 'https://lambda.us-east-1.amazonaws.com',
          });

const params = {
                FunctionName: 'FunctionName', eg: demo-dev-index-function
                InvocationType: 'RequestResponse',
                // Payload: JSON.stringify({ data: 'foo' }),
                Payload: JSON.stringify({
                    query: `{
                            findIdentityWithPhoneNumber(phoneNumber: "99999999") {
                                ObjectId
                                uuid
                            }
                        }`
                }),
            }

const response = await lambda.invoke(params).promise()
console.log(response);

{
  StatusCode: 200,
  Payload: '{"statusCode":404,"body":"{\\"statusCode\\":404,\\"message\\":\\"Cannot GET /\\",\\"error\\":\\"Not Found\\"}","headers":{"x-powered-by":"Express","access-control-allow-origin":"*","content-type":"application/json; charset=utf-8","content-length":"63","etag":"W/\\"3f-GR0G8sZfNVmVbqqGkyrPOefU7Ys\\"","date":"Wed, 28 Apr 2021 10:05:40 GMT","connection":"close"},"isBase64Encoded":false}'
}

//serverless.yml for the called function

service: serviceName
useDotenv: true
  
provider:
  lambdaHashingVersion: 20201221
  name: aws
  runtime: nodejs12.x
  memorySize: 256
  stage: ${opt:stage, 'dev'}
  region: ${opt:region}
  environment:
    SERVICE: ${self:service}
    STAGE: ${self:provider.stage}
    REGION: ${self:provider.region}
    VERSION: ${env:VERSION}
    LOCALE: ${env:LOCALE}

  apiGateway:
    shouldStartNameWithService: true
  iam:
    role:
      statements:
        - 
          Effect: "Allow"
          Action:
            - "lambda:InvokeFunction"
          Resource: "*"
        - 
          Effect: Allow
          Action:
            - dynamodb:DescribeTable
            - dynamodb:Query
            - dynamodb:Scan
            - dynamodb:GetItem
            - dynamodb:PutItem
            - dynamodb:UpdateItem
            - dynamodb:DeleteItem
          Resource: arn:aws:dynamodb:${self:provider.region}:*:*

plugins:
  - serverless-plugin-typescript
  - serverless-dynamodb-local
  - serverless-offline

# remove the unnecessary packages to keep small upload size
package:
  patterns:
    - '!node_modules/typescript/**'
    - '!node_modules/@types/**'

custom:
  dynamodb:
    stages:
      - ${self:provider.stage}
    start:
      port: 8000
      inMemory: true
      migrate: true
      seed: false

functions:
  index-function:
    handler: src/index.handler
    events:
      - http:
          cors: true
          path: '{proxy+}'
          method: any

resources:
  - ${file(resource/dynamodb.yml)}

@epiphaneSpecter You are trying to do lambda Synchronous invocation, therefore u need add another function handler for that

functions:
  custom-function:
    handler: src/custom-function.handler

however, it is more easy to just use the graphql client and invoke the same index-function through the API Gateway.

@epiphaneSpecter You are trying to do lambda Synchronous invocation, therefore u need add another function handler for that

functions:
  custom-function:
    handler: src/custom-function.handler

however, it is more easy to just use the graphql client and invoke the same index-function through the API Gateway.

ok okay, but i would have to pay twice. i.e. both the lambda execution resources and the call through API Gateway.

@hardyscc by declaring a new handler this time, the starting of nestjs will be done in a classic way as is nestjs done by default?

@epiphaneSpecter Yes u need to bootstrap the nestjs server (i.e. src/index.ts) and invoke the function yourself.

@epiphaneSpecter normally if just simple operation i won't bootup nestjs at all, and just instance a dynamodb model then do the update

@epiphaneSpecter Yes u need to bootstrap the nestjs server (src/index.ts) and invoke the function yourself.

excuse me I'm a little lost, suppose I have two projects A and B. I'm currently in B and want to invoke A. I have to define a new hanlder in the A which will process my request (which does not come from API Gateway). So my question is: the logic that should be in my new handler should be how, just an idea.

@epiphaneSpecter Yes u need to bootstrap the nestjs server (src/index.ts) and invoke the function yourself.

excuse me I'm a little lost, suppose I have two projects A and B. I'm currently in B and want to invoke A. I have to define a new hanlder in the A which will process my request (which does not come from API Gateway). So my question is: the logic that should be in my new handler should be how, just an idea.

the new handler is just a normal lamdba handler like that

export const handler = async (event, context) => { ... }

@epiphaneSpecter Yes u need to bootstrap the nestjs server (src/index.ts) and invoke the function yourself.

excuse me I'm a little lost, suppose I have two projects A and B. I'm currently in B and want to invoke A. I have to define a new hanlder in the A which will process my request (which does not come from API Gateway). So my question is: the logic that should be in my new handler should be how, just an idea.

the new handler is just a normal lamdba handler like that

export const handler = async (event, context) => { ... }

ok, tks