我正在关注教程https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html
对于仅使用switch
处理graphql查询有一些疑问。
是否有更好的方法来处理更复杂的请求?
答案 0 :(得分:3)
由您决定如何在AppSync API中设置lambda。每个解析器都具有lambda函数并由一个函数负责单个解析器是完全合理的。您也可以采用类似于本教程的方法,并使用单个函数和一些轻量级路由代码来照顾正确的函数。由于lambda的容器预热如何工作(尤其是Java和C#,VM启动时间可能加起来),因此使用单个函数通常可以带来一些性能优势。
以下是我过去采用的一些方法:
选项1:JS
这种方法使用JavaScript,对于以前运行过自己的GraphQL服务器的用户应该感到熟悉。
const Resolvers = {
Query: {
me: (source, args, identity) => getLoggedInUser(args, identity)
},
Mutation: {
login: (source, args, identity) => loginUser(args, identity)
}
}
exports.handler = (event, context, callback) => {
// We are going to wire up the resolver to give all this information in this format.
const { TypeName, FieldName, Identity, Arguments, Source } = event
const typeResolver = Resolvers[TypeName]
if (!typeResolver) {
return callback(new Error(`No resolvers found for type: "${TypeName}"`))
}
const fieldResolver = typeResolver[FieldName]
if (!fieldResolver) {
return callback(new Error(`No resolvers found for field: "${FieldName}" on type: "${TypeName}"`), null)
}
// Handle promises as necessary.
const result = fieldResolver(Source, Arguments, Identity);
return callback(null, result)
};
然后可以使用AppSync中的标准lambda解析器。现在,我们必须手动提供TypeName和FieldName。
#**
The value of 'payload' after the template has been evaluated
will be passed as the event to AWS Lambda.
*#
{
"version" : "2017-02-28",
"operation": "Invoke",
"payload": {
"TypeName": "Query",
"FieldName": "me",
"Arguments": $util.toJson($context.arguments),
"Identity": $util.toJson($context.identity),
"Source": $util.toJson($context.source)
}
}
选项2:执行
出于好奇,我还通过AppSync成功使用了go lambda函数。这是一种对我有效的方法。
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/lambda"
"github.com/fatih/structs"
"github.com/mitchellh/mapstructure"
)
type GraphQLPayload struct {
TypeName string `json:"TypeName"`
FieldName string `json:"FieldName"`
Arguments map[string]interface{} `json:"Arguments"`
Source map[string]interface{} `json:"Source"`
Identity map[string]interface{} `json:"Identity"`
}
type ResolverFunction func(source, args, identity map[string]interface{}) (data map[string]interface{}, err error)
type TypeResolverMap = map[string]ResolverFunction
type SchemaResolverMap = map[string]TypeResolverMap
func resolverMap() SchemaResolverMap {
return map[string]TypeResolverMap{
"Query": map[string]ResolverFunction{
"me": getLoggedInUser,
},
}
}
func Handler(ctx context.Context, event GraphQLPayload) (map[string]interface{}, error) {
// Almost the same as the JS option.
resolvers := resolverMap()
typeResolver := resolvers[event.TypeName]
if typeResolver == nil {
return nil, fmt.Errorf("No type resolver for type " + event.TypeName)
}
fieldResolver := typeResolver[event.FieldName]
if fieldResolver == nil {
return nil, fmt.Errorf("No field resolver for field " + event.FieldName)
}
return fieldResolver(event.Source, event.Arguments, event.Identity)
}
func main() {
lambda.Start(Handler)
}
/**
* Resolver Functions
*/
/**
* Get the logged in user
*/
func getLoggedInUser(source, args, identity map[string]interface{}) (data map[string]interface{}, err error) {
// Decode the map[string]interface{} into a struct I defined
var typedArgs myModelPackage.GetLoggedInUserArgs
err = mapstructure.Decode(args, &typedArgs)
if err != nil {
return nil, err
}
// ... do work
res, err := auth.GetLoggedInUser()
if err != nil {
return nil, err
}
// Map the struct back to a map[string]interface{}
return structs.Map(out), nil
}
// ... Add as many more as needed
然后,您可以使用与选项1中使用的相同的解析器模板。还有许多其他方法可以执行此操作,但这是一种对我有效的方法。
希望这会有所帮助:)
答案 1 :(得分:2)
您不会被迫使用单个AWS Lambda来处理每个请求。对于本教程,新手更容易理解它,因此他们使用了这种方法。
但是最终由您自己决定如何实现它。一种替代方法是为每个解析器创建一个单独的AWS Lambda,以消除switch
并遵循Single Responsibility Principle (SRP)。
答案 2 :(得分:0)
您可以将所有查询代理到graphql-server
答案 3 :(得分:0)
Apollo GraphQL Server提供了一个很好的设置,可以在AWS Lambda中部署GraphQL服务器。