From 7c9671350487988ac214405a69237e86bfac7dd8 Mon Sep 17 00:00:00 2001 From: canonical Date: Tue, 27 Aug 2024 20:53:06 +0800 Subject: [PATCH] =?UTF-8?q?xbiz=E6=A8=A1=E5=9E=8B=E4=B8=AD=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E7=9A=84loader=E5=A2=9E=E5=8A=A0batchLoader=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../biz/impl/BizModelToGraphQLDefinition.java | 39 ++++++++++++++++++- .../java/io/nop/biz/model/BizLoaderModel.java | 26 +++++++++++++ .../src/main/resources/nop-vfs-index.txt | 2 + .../core/fetcher/BeanMethodBatchFetcher.java | 14 ++++--- .../resources/_vfs/nop/rpc/imp/api.imp.xml | 4 ++ 5 files changed, 78 insertions(+), 7 deletions(-) diff --git a/nop-biz/src/main/java/io/nop/biz/impl/BizModelToGraphQLDefinition.java b/nop-biz/src/main/java/io/nop/biz/impl/BizModelToGraphQLDefinition.java index 15b50daf6..b6f5701d8 100644 --- a/nop-biz/src/main/java/io/nop/biz/impl/BizModelToGraphQLDefinition.java +++ b/nop-biz/src/main/java/io/nop/biz/impl/BizModelToGraphQLDefinition.java @@ -17,10 +17,12 @@ import io.nop.biz.model.BizReturnModel; import io.nop.core.context.action.IServiceAction; import io.nop.core.lang.eval.IEvalAction; +import io.nop.core.lang.eval.IEvalScope; import io.nop.core.type.IGenericType; import io.nop.graphql.core.GraphQLConstants; import io.nop.graphql.core.IDataFetcher; import io.nop.graphql.core.IDataFetchingEnvironment; +import io.nop.graphql.core.IGraphQLExecutionContext; import io.nop.graphql.core.ast.GraphQLArgumentDefinition; import io.nop.graphql.core.ast.GraphQLDefinition; import io.nop.graphql.core.ast.GraphQLFieldDefinition; @@ -29,6 +31,7 @@ import io.nop.graphql.core.ast.GraphQLNamedType; import io.nop.graphql.core.ast.GraphQLObjectDefinition; import io.nop.graphql.core.ast.GraphQLType; +import io.nop.graphql.core.fetcher.BeanMethodBatchFetcher; import io.nop.graphql.core.fetcher.ServiceActionFetcher; import io.nop.graphql.core.reflection.ArgBuilders; import io.nop.graphql.core.reflection.EvalGraphQLArgsNormalizer; @@ -45,12 +48,17 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.BiFunction; import java.util.function.Function; +import java.util.stream.Collectors; import static io.nop.graphql.core.GraphQLErrors.ARG_ACTION_NAME; import static io.nop.graphql.core.GraphQLErrors.ARG_ARG_NAME; +import static io.nop.graphql.core.GraphQLErrors.ARG_METHOD_NAME; +import static io.nop.graphql.core.GraphQLErrors.ARG_OBJ_NAME; import static io.nop.graphql.core.GraphQLErrors.ARG_TYPE; import static io.nop.graphql.core.GraphQLErrors.ERR_GRAPHQL_ACTION_ARG_TYPE_NOT_OBJ_TYPE; +import static io.nop.graphql.core.GraphQLErrors.ERR_GRAPHQL_BATCH_LOAD_METHOD_MUST_RETURN_LIST; public class BizModelToGraphQLDefinition { public static final BizModelToGraphQLDefinition INSTANCE = new BizModelToGraphQLDefinition(); @@ -104,7 +112,7 @@ public GraphQLFieldDefinition toBuilder(String thisObjName, BizLoaderModel loade if (args != null) field.setArguments(args); - IDataFetcher fetcher = buildFetcher(loaderModel, typeRegistry); + IDataFetcher fetcher = buildFetcher(thisObjName, loaderModel, typeRegistry); field.setFetcher(fetcher); field.setAutoCreate(loaderModel.isAutoCreateField()); return field; @@ -125,20 +133,47 @@ public IServiceAction buildAction(BizActionModel actionModel, IServiceActionArgB return new EvalServiceAction(source, argBuilders); } - IDataFetcher buildFetcher(BizLoaderModel loaderModel, TypeRegistry typeRegistry) { + IDataFetcher buildFetcher(String bizObjName, BizLoaderModel loaderModel, TypeRegistry typeRegistry) { IEvalAction source = loaderModel.getSource(); if (source == null) source = ctx -> null; Map> argBuilders = new LinkedHashMap<>(); + BizActionArgModel contextSourceArg = null; for (BizActionArgModel arg : loaderModel.getArgs()) { + if (arg.getKind() == BizActionArgKind.ContextSource) + contextSourceArg = arg; + Function argBuilder = getFetcherArg(arg.getKind(), arg.getName(), arg.getType()); argBuilders.put(arg.getName(), argBuilder); } + + if (contextSourceArg != null && contextSourceArg.getType() != null && contextSourceArg.getType().isCollectionLike()) { + // 如果是集合类型的参数,则表示这是一个BatchLoader + if (!loaderModel.isReturnList()) { + throw new NopException(ERR_GRAPHQL_BATCH_LOAD_METHOD_MUST_RETURN_LIST).source(loaderModel) + .param(ARG_OBJ_NAME, bizObjName).param(ARG_METHOD_NAME, loaderModel.getName()); + } + int sourceIndex = loaderModel.getArgs().indexOf(contextSourceArg); + String loaderName = bizObjName + "@" + loaderModel.getName(); + + List> argsList = loaderModel.getArgs() + .stream().map(arg -> argBuilders.get(arg.getName())) + .collect(Collectors.toList()); + + return new BeanMethodBatchFetcher(loaderName, newFetcher(source, loaderModel), argsList, sourceIndex); + } return new EvalActionDataFetcher(source, argBuilders); } + private static BiFunction newFetcher(IEvalAction source, BizLoaderModel loaderModel) { + return (args, ctx) -> { + IEvalScope scope = loaderModel.newEvalScope(args, ctx.getEvalScope()); + return source.invoke(scope); + }; + } + IServiceActionArgBuilder getArgBuilder(BizActionArgKind kind, String name, IGenericType type) { if (kind == BizActionArgKind.RequestBean) { return ArgBuilders.getActionRequest(type); diff --git a/nop-biz/src/main/java/io/nop/biz/model/BizLoaderModel.java b/nop-biz/src/main/java/io/nop/biz/model/BizLoaderModel.java index a66ef3576..7c4d3ee7d 100644 --- a/nop-biz/src/main/java/io/nop/biz/model/BizLoaderModel.java +++ b/nop-biz/src/main/java/io/nop/biz/model/BizLoaderModel.java @@ -8,9 +8,35 @@ package io.nop.biz.model; import io.nop.biz.model._gen._BizLoaderModel; +import io.nop.core.context.IEvalContext; +import io.nop.core.lang.eval.IEvalScope; +import io.nop.core.type.IGenericType; public class BizLoaderModel extends _BizLoaderModel { public BizLoaderModel() { } + + public IEvalScope newEvalScope(Object[] args, IEvalContext ctx) { + IEvalScope scope = ctx.getEvalScope().newChildScope(); + for (int i = 0, n = args.length; i < n; i++) { + String name = getArgs().get(i).getName(); + scope.setLocalValue(null, name, args[i]); + } + return scope; + } + + public IGenericType getReturnType() { + BizReturnModel returnModel = getReturn(); + if (returnModel == null) + return null; + return returnModel.getType(); + } + + public boolean isReturnList() { + IGenericType returnType = getReturnType(); + if (returnType == null) + return false; + return returnType.isListLike(); + } } diff --git a/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt b/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt index 47209e5cf..9a96f89c4 100644 --- a/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt +++ b/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt @@ -1159,6 +1159,8 @@ /nop/wf/pages/NopWfDefinition/NopWfDefinition.lib.xjs /nop/wf/pages/NopWfDefinition/NopWfDefinition.view.xml /nop/wf/pages/NopWfDefinition/_gen/_NopWfDefinition.view.xml +/nop/wf/pages/NopWfDefinition/designer.page.yaml +/nop/wf/pages/NopWfDefinition/flow.lib.js /nop/wf/pages/NopWfDefinition/main.page.yaml /nop/wf/pages/NopWfDefinition/ofd-models.lib.css /nop/wf/pages/NopWfDefinition/ofd-models.lib.js diff --git a/nop-graphql/nop-graphql-core/src/main/java/io/nop/graphql/core/fetcher/BeanMethodBatchFetcher.java b/nop-graphql/nop-graphql-core/src/main/java/io/nop/graphql/core/fetcher/BeanMethodBatchFetcher.java index 8fc497829..2c8316b22 100644 --- a/nop-graphql/nop-graphql-core/src/main/java/io/nop/graphql/core/fetcher/BeanMethodBatchFetcher.java +++ b/nop-graphql/nop-graphql-core/src/main/java/io/nop/graphql/core/fetcher/BeanMethodBatchFetcher.java @@ -18,6 +18,7 @@ import org.dataloader.DataLoaderFactory; import java.util.List; +import java.util.function.BiFunction; import java.util.function.Function; /** @@ -25,16 +26,19 @@ */ public class BeanMethodBatchFetcher implements IDataFetcher { private final String loaderName; - private final Object bean; - private final IFunctionModel function; + private final BiFunction realFetcher; private final List> argBuilders; private final int sourceIndex; public BeanMethodBatchFetcher(String loaderName, Object bean, IFunctionModel function, List> argBuilders, int sourceIndex) { + this(loaderName, (args, context) -> function.invoke(bean, args, context.getEvalScope()), argBuilders, sourceIndex); + } + + public BeanMethodBatchFetcher(String loaderName, BiFunction realFetcher, + List> argBuilders, int sourceIndex) { this.loaderName = loaderName; - this.bean = bean; - this.function = function; + this.realFetcher = realFetcher; this.argBuilders = argBuilders; this.sourceIndex = Guard.checkPositionIndex(sourceIndex, argBuilders.size(), "sourceIndex"); } @@ -52,7 +56,7 @@ public Object get(IDataFetchingEnvironment env) { } BatchLoader batchLoader = keys -> { args[sourceIndex] = keys; - return FutureHelper.futureCall(() -> function.invoke(bean, args, context.getEvalScope())); + return FutureHelper.futureCall(() -> realFetcher.apply(args, context)); }; loader = DataLoaderFactory.newDataLoader(batchLoader); context.registerDataLoader(loaderName, loader); diff --git a/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml b/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml index 50ef2c6e8..42879ecd4 100644 --- a/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml +++ b/nop-rpc/nop-rpc-model/src/main/resources/_vfs/nop/rpc/imp/api.imp.xml @@ -40,6 +40,10 @@ + + + +