Quarkus/Mutiny 中是否需要递归?

Is recursion necessary in Quarkus/Mutiny?

我正在尝试使用 Redis 的 scan 功能,该功能需要调用直到返回的光标为“0”。

这种方法可行,但感觉过于复杂 - 有没有不用递归的方法?

Uni<Object> callScanRecursively(String cursorNum, List<String> results) {
  List<String> args = new ArrayList<>(List.of(cursorNum, "MATCH", "*"));
  return reactiveRedisClient.scan(args)
      .onItem()
      .transformToUni(item -> {
            List<String> keysList = new ArrayList<>();
            item.get(1).forEach(k -> {
              keysList.add(k.toString());
            });
            results.addAll(keysList);

            if (item.get(0).toString().equals("0")) {
              return Uni.createFrom().item(results);
            } else {
              String nextCursorNum = item.get(0).toString();
              return callScanRecursively(nextCursorNum, results);
            }
          }
      );
}

List<String> results = new ArrayList<>();
String startingCursorRedis = "0";
callScanRecursively(startingCursorRedis, results)
    .subscribe()
    .with(item ->
        LOGGER.info(item)
    );

您可以使用 MultiRepeat 通过 Uni 发射器收集 ReactiveRedisClient#scan 结果,同时给定条件 response.get(0).toString().equals("0") 仍未满足:

单一发射器

Multi<String> callScan(String initialCursor) {
    final AtomicReference<String> cursorReference = new AtomicReference<>(initialCursor);
    return Multi.createBy()
            .repeating()
            .<AtomicReference<String>, List<String>>uni(
                    () -> cursorReference,
                    (state, emitter) -> reactiveRedisClient.scan(List.of(state.get(), "MATCH", "*"))
                            .subscribe()
                            .with(response -> {
                                if (response.get(0).toString().equals("0")) {
                                    cursorReference.set(null);
                                } else {
                                    state.set(response.get(0).toString());
                                }
                                java.util.List<String> keysList = new ArrayList<>();
                                response.get(1).forEach(k -> keysList.add(k.toString()));
                                emitter.complete(keysList);
                            })
            )
            .whilst(o -> cursorReference.get() != null)
            .flatMap(l -> Multi.createFrom().iterable(l));
}

大学

如果您不需要对发出的项目进行更多控制,甚至更简单:

Multi<String> callScan(String initialCursor) {
    ReactiveRedisClientImpl reactiveRedisClient = new ReactiveRedisClientImpl();
    final AtomicReference<String> cursorReference = new AtomicReference<>(initialCursor);
    return Multi.createBy()
            .repeating()
            .uni(
                    () -> cursorReference,
                    (state) -> reactiveRedisClient.scan(List.of(state.get(), "MATCH", "*"))
                            .invoke(response -> {
                                if (response.get(0).toString().equals("0")) {
                                    cursorReference.set(null);
                                } else {
                                    state.set(response.get(0).toString());
                                }
                            })
                            .map(response -> {
                                List<String> keysList = new ArrayList<>();
                                response.get(1).forEach(k -> keysList.add(k.toString()));
                                return keysList;
                            })
            )
            .whilst(o -> cursorReference.get() != null)
            .flatMap(l -> Multi.createFrom().iterable(l));
}