Project Reactor:终止后的访问上下文

时间:2019-06-27 15:41:44

标签: java logging project-reactor

我有一个反应性(Mono)流,该流以多个步骤处理传入的数据。其中一些步骤收集Info对象中的某种日志数据。该对象的实例通过Reactor的subscriberContext()函数(请参见Project Reactor Docs)传递到这些处理步骤。在所有处理结束时,无论流是否成功,都必须保存Info对象。

我有一个示例实现:

import java.time.Instant;
import reactor.core.publisher.Mono;

public class CtxTest {

    static class Info {
        Instant timeStamp = Instant.now();
        String input;
        @Override
        public String toString() {
            return timeStamp.toString() + ": " + input;
        }
    }

    public static void main(String... args) {
        final String contextKey = "key";

        Mono<String> mono = Mono.just("hello")
                .flatMap(s -> Mono.subscriberContext()
                        .map(ctx -> transform(s, ctx.get(contextKey))))
                .doAfterTerminate(() -> saveInfo(Mono.subscriberContext().block().get(contextKey))) // does not work
                .subscriberContext(ctx -> ctx.put(contextKey, new Info()));

        mono.subscribe(System.out::println);
    }

    static String transform(String input, Info info) {
        info.input = input;
        return input.toUpperCase();
    }

    static void saveInfo(Info info) {
        System.out.println(info);
    }
}

在这里,transform是一个处理步骤,它转换输入的String并另外用日志记录数据填充Info对象。我已验证.flatMap步骤是否按预期进行。

但是,.doAfterTerminate步骤给出了java.util.NoSuchElementException: Context is empty异常。如何归档所需的行为?

旁注: 我发现了一些使用.doOnEach访问上下文的示例。如果我将.doAfterTerminate行替换为以下行:

.doOnEach(s -> saveInfo(s.getContext().get(contextKey)))

我成功地使用非空上下文对象调用了saveInfo。有趣的是,一次运行main会两次调用该函数。

0 个答案:

没有答案