sam-goodwin / punchcard

Type-safe AWS infrastructure.
Apache License 2.0
507 stars 20 forks source link

executorService.apiIntegration can't find the resource id on runtime #63

Closed pocesar closed 4 years ago

pocesar commented 4 years ago

I tried many ways using apigateway with executorService, the environment variables are properly set, but the code always return the same error:

2019-12-22T19:41:31.602Z    87da8da1-91e0-4657-9f77-d897e7fca735    INFO    not index
2019-12-22T19:41:31.604Z    87da8da1-91e0-4657-9f77-d897e7fca735    INFO    { cim23c27ve: undefined, n2fjvw: undefined }
2019-12-22T19:41:31.605Z    87da8da1-91e0-4657-9f77-d897e7fca735    INFO    n2fjvw
2019-12-22T19:41:31.605Z    87da8da1-91e0-4657-9f77-d897e7fca735    INFO    
{}
2019-12-22T19:41:31.606Z    87da8da1-91e0-4657-9f77-d897e7fca735    ERROR   Error: could not find resource for resource id: n2fjvw
    at LambdaIntegration.findResource (/var/task/app.js:130829:19)
    at Function.handle (/var/task/app.js:91225:46)
    at /var/task/app.js:64799:47
    at Runtime.exports.handler (/var/task/index.js:22:12)
2019-12-22T19:41:31.606Z    87da8da1-91e0-4657-9f77-d897e7fca735    ERROR   Invoke Error    
{
    "errorType": "Error",
    "errorMessage": "could not find resource for resource id: n2fjvw",
    "stack": [
        "Error: could not find resource for resource id: n2fjvw",
        "    at LambdaIntegration.findResource (/var/task/app.js:130829:19)",
        "    at Function.handle (/var/task/app.js:91225:46)",
        "    at /var/task/app.js:64799:47",
        "    at Runtime.exports.handler (/var/task/index.js:22:12)"
    ]
}

I put some console.logs on the api-gateway/resource to see what is going on, it seems that the call to "findResource" is assigning an "undefined" resource on:

image

and since "resourceMappings" is empty from the logs

image

maybe a racing condition? because "resource" isn't empty when mapResource is called. as you can see, resourceMappings is empty, but index is not, which seems weird, since the environment variable for resource_id_apibusiness7765B3D2 is being set to n2fjvw, which means it's being called at least in some moment

const api = new p.ApiGateway.Api(stack, 'api')

const endpoint = executorService.apiIntegration(stack, 'api-integration', {
  depends: p.Core.Dependency.none,
})

const getBusinessRes = api.addResource('business')

getBusinessRes.setGetMethod({
  integration: endpoint,
  responses: {
    [p.ApiGateway.StatusCode.Ok]: p.Shape.struct({
      result: p.Shape.dynamic
    }),
    [p.ApiGateway.StatusCode.InternalError]: p.Shape.struct({
      result: p.Shape.dynamic,
      error: p.Shape.string()
    })
  },
  request: {
    shape: p.Shape.struct({
      code: p.Shape.string()
    }),
    mappings: {
      code: p.ApiGateway.$input.params('code')
    }
  },
  handle: async (r) => {
    try {
      return p.ApiGateway.response(p.ApiGateway.StatusCode.Ok, {
        result: await getBusiness(r.code)
      })
    } catch (e) {
      return p.ApiGateway.response(p.ApiGateway.StatusCode.InternalError, {
        result: null,
        error: e.message
      })
    }
  }
})
sam-goodwin commented 4 years ago

Looks like a bug! The API Gateway stuff is in need of a re-write I think. Will start debugging this one ASAP.

sam-goodwin commented 4 years ago

I think it's a consequence of Build vs Run. My hunch is that mapResource is not called at runtime so the result of this.resourceMappings[uniqueId] is undefined.

sam-goodwin commented 4 years ago

Yep!

It's called in makeHandler:

https://github.com/punchcard/punchcard/blob/ab74ce565254d6490500ce388a92885e7345f600/packages/punchcard/lib/api-gateway/resource.ts#L192-L193

Which is called in addMethod inside a Build context:

https://github.com/punchcard/punchcard/blob/ab74ce565254d6490500ce388a92885e7345f600/packages/punchcard/lib/api-gateway/resource.ts#L115-L124

sam-goodwin commented 4 years ago

Just released version 0.11.0 that should fix this. Hope it works now!