serverless-appsync / serverless-appsync-simulator

A simple wrapper around Amplify AppSync Simulator to test serverless AppSync Apis
MIT License
127 stars 69 forks source link

Supporting Multiple Lambda Runtimes #33

Closed zprobst closed 2 years ago

zprobst commented 4 years ago

Is your feature request related to a problem? Please describe. It currently seems that this package supports only javascript lambda resolvers. Am I missing something? Many other languages could be used with serverless. Additionally, this tool is then coupled with an opinion that the lambda resolvers cannot be written in languages outside of javascript.

Describe the solution you'd like I don't know the first thing about Javascript ( I am a python and rust dev mostly), so bear with me.

With the dependency on the serverless offline plugin, it seems instead we could invoke the lambda with the aws sdk as the method described here in the serverless offline docs. Since this plugin is already required, there is no net gain in dependencies. The amplify-nodejs-function-runtime-provider could be removed in favor of adding the aws-sdk and using the already required serverless-offline

Describe alternatives you've considered For a lot of languages (outside of what amplify supports) there are no alternatives for local development. Even inside of the amplify ecosystem, if some of its opinionated defaults works for you, you are kicked to doing everything by hand or using serverless. To that end, I think there should be some demand for this.

Additional context I am willing to contribute this back if the maintainers are willing to have the feature and willing to bear with some terrible javascript code as a I learn. If its not inline with the direction, I can always work on a custom solution.

bboure commented 4 years ago

Hi @zprobst Thank you for your feedback.

Multiple runtimes is definitely something we want to implement in this plugin. I haven't implemented them (yet) for several reasons:

With the dependency on the serverless offline plugin...

In fact, the use of serverless offline is not totally necessary. We used it for convenience only. We use the hooks that spins up the simulator. Most importantly, it is used to make it work with https://github.com/99xt/serverless-dynamodb-local easily, since severless-offline stats the DynamoDb simulator too. We could add custom commands in order to spin up the simulator directly. This would actually be really cool since probably most people don't even need the API Gateway simulator when working with AppSync. (In that case, if you use dynamodb, you would have to start it manually too)

The amplify-nodejs-function-runtime-provider could be removed in favor of adding the aws-sdk and using the already required serverless-offline

Since this plugin relies on amplify-cli, it makes more sense I guess to use their dependencies, for compatibility reasons.

They now have packages for: python: https://www.npmjs.com/package/amplify-python-function-runtime-provider java: https://www.npmjs.com/package/amplify-java-function-runtime-provider go: https://www.npmjs.com/package/amplify-go-function-runtime-provider dotnet: https://www.npmjs.com/package/amplify-dotnet-function-runtime-provider

I haven't had time to look into it yet but it seems there is a getInvoker function that returns the ìnvoke function that we use statically here

It does not seem easy to implement though as this relies on a context object which I am not sure where it comes from. This requires a bit of investigation but it seems possible.

I understand you are not familiar with javascript, so it might not be the job for you, however if you are willing to give it a try, you are welcome. I could give you a hand later to adjust the last screws and bolts. :) Otherwise, I could try to find some time to do this but I cannot promise when this could be ready.

cdavis21 commented 4 years ago

+1 (currently using python for scientific libraries)

theoribeiro commented 3 years ago

Hi @bboure!

I investigated the alternative you proposed in the above comment and in general lines it does work. However, there are a few problems with the runtime providers that would make this solution not ideal at this point.

For instance, the python runtime provider expects a certain path for your function to be in (your functions need to be in ./src/), but if you do that then you need to change your serverless.yml configuration file in order to deploy successfully, which would send the wrong path to the python runtime when you are testing (it would again search in ./src, resulting in trying to get code from ./src/src/handler.py).

The solution I found, for now, and which I think works pretty well in my case, is to just use the built-in Serverless Invoke Local plugin to invoke the functions. This way, we don't need to rely on Amplify for that (and Serverless does a pretty good job with invoking the functions locally).

You can see the proposed changes here: https://github.com/bboure/serverless-appsync-simulator/compare/master...theoribeiro:master

Since I know this was not the solution you proposed, I didn't create a PR but I'm happy to do so if you think this would make sense.

Let me know your thoughts.

bboure commented 3 years ago

@theoribeiro Thanks for taking time to investigate this. The solution to your path issue might be to just change the location option It allows you to change the location of the handler, for example when using webpack, or in your case. (see the README file).

I opened the PR for you and will have a look at it.

MarcusJones commented 3 years ago

Just ran into this as well, took me a while to realize Python wasn't supported! I had a project that mixes both JS and Python resolvers, so it was extra confusing why JS worked through appsync and Python didn't, even though I could still invoke local! Would be great to get an error message or some other feedback.

seanvm commented 3 years ago

I had the same issue as theoribeiro trying to get the amplify runtime working (in my case for Go). It expected a very specific path and context to be available.

@theoribeiro I tried your updated code and it does seem to work, however for Golang it is very slow, which I believe is due to sls invoke local spinning up a container for every request even though serverless offline is running.

An alternative that seems to be working for me is to use the invocation endpoints provided by serverless offline:

http://localhost:3002/2015-03-31/functions/{your-function}/invocations

@bboure I noticed you have a flow that uses Axios to make an http request to "external" functions. I'm curious whether you explored this at all as a direct replacement for using amplify-nodejs-function-runtime-provider?

The immediate downside I can see to my method is that it would create a much larger dependency on serverless-offline

bboure commented 3 years ago

@bboure I noticed you have a flow that uses Axios to make an http request to "external" functions. I'm curious whether you explored this at all as a direct replacement for using amplify-nodejs-function-runtime-provider?

Yeah. I actually never thought about that and it seems like a reasonable workaround. The downside is indeed that it enforces dependency on serverless-offline, but it's kind of already the case.

Let's move this discussion in the PR #74

bboure commented 2 years ago

multiple runtimes should now work via serverless-offline since v0.17.0