从 graphql-java-kickstart 迁移到 spring-graphql 时重新配置数据加载器

问题描述 投票:0回答:1

我正在将 GraphQl-java-kickstart 项目迁移到 Spring-GraphQl,因为在项目中实现 GraphQL 时 Spring-GraphQl 不可用。迁移的主要原因是 Spring 提供的自动配置和基于注释的方法可能有助于删除初始 GraphQl 项目中的许多复杂的样板代码。

kickstart 数据加载器配置中有一个数据加载器注册,我似乎无法在新的 Spring Graphql 配置设置中重新创建它。在 kickstart grapql 配置中,创建一个数据加载器并将其用作另一个数据加载器中的方法参数(如下简化):

@Component
public class RequestContextBuilder extends DefaultGraphQLServletContextBuilder {

    @Override
    public GraphQLKickstartContext build(HttpServletRequest request, HttpServletResponse response) {
        
        Map<Object, Object> map = new HashMap<>();
        // ... 
        return GraphQLKickstartContext.of(buildDataLoaderRegistry(), map);
    }
    
    private DataLoaderRegistry buildDataLoaderRegistry() {

        var noBatching = new DataLoaderOptions().setBatchingEnabled(false);

        var dataLoaderRegistry = new DataLoaderRegistry();

        var firstLoader = DataLoaderFactory.newDataLoader(
                ids1 -> supplyAsync(() -> firstService.getItems(ids1), traceableExecutorService),
                noBatching
        );
        dataLoaderRegistry.register("first", firstLoader);


        var secondLoader = DataLoaderFactory.newDataLoader(
                ids2 -> supplyAsync(() -> ((Function<List<ID>, List<Item>>) ids2 -> 
                  secondService.loadUsingOtherLoader(ids2, firstLoader)).apply(ids), traceableExecutorService),
                noBatching
        );
        dataLoaderRegistry.register("second", secondLoader);

        return dataLoaderRegistry;
    }
}

...
@Service
public class SecondService {
  
  public List<Item> loadUsingOtherLoader(List<ID> ids, DataLoader<ID, Item> firstLoader) {
    
    return ids.stream()
              .map(firstloader::load)
              . //
              .toList();
  }
}

我似乎无法使用 BatchLoaderRegistry 在 Spring-GraphQl 配置中重新创建此设置,因为加载程序作为 lambda 而不是 DataLoaders 传递,并且无法从注册表中检索:

@Configuration
public class RequestContextBuilder {

    public RequestContextBuilder(BatchLoaderRegistry registry, FirstService firstService, SecondService secondService) {
    
        registry.forName("first")
                .withOptions(BATCHING_DISABLED)
                .registerBatchLoader((ids, env) -> Flux.fromStream(ids.stream()).map(firstService::getItems));
        
        registry.forName("second")
                .withOptions(BATCHING_DISABLED)
                .registerBatchLoader((ids, env) -> Flux.fromStream(ids.stream()).map(secondService::loadUsingOtherLoader));
        }
    }

}

尽管在理想情况下,第二个加载器不需要依赖于第一个加载器,但此迁移的初始阶段是从 graphql-kickstart 切换到 spring-graphql,并进行尽可能少的更改。在稍后的重构阶段,加载器将被解耦,应用弹簧逻辑+注释等。

有谁知道这个问题如何解决吗?

spring-boot graphql graphql-java spring-graphql
1个回答
1
投票

对于任何感兴趣的人,我设法通过使用

BatchLoaderEnvironment
:

检索其他数据加载器来解决此问题
@Configuration
public class RequestContextBuilder {

    public RequestContextBuilder(BatchLoaderRegistry registry, FirstService firstService, SecondService secondService) {
    
        registry.forName("first")
                .withOptions(BATCHING_DISABLED)
                .registerBatchLoader((ids, env) -> Flux.fromStream(ids.stream()).map(firstService::getItems));
        
        registry.forName("second")
                .withOptions(BATCHING_DISABLED)
                .registerBatchLoader((ids, env) -> {
     
              var dfe = obtainDfeFromEnvironment(env);
              var firstLoader = dfe.getDataLoader("first");
              // .... etc
        });
    }

    private static DataFetchingEnvironment obtainDfeFromEnvironment(BatchLoaderEnvironment env) {

          return env.getKeyContextsList().stream()
                .filter(DataFetchingEnvironment.class::isInstance)
                .map(DataFetchingEnvironment.class::cast)
                .findFirst()
                .orElseThrow();
    }
}

并在调用数据加载器时将

DataFetchingEnvironment
作为第二个参数传递:

dfe.<SomeId, List<SomeClass>>getDataLoader("second").load(someId, dfe);
© www.soinside.com 2019 - 2024. All rights reserved.