LoginSignup
1
0

More than 1 year has passed since last update.

Reactorのdeferの使い方

Last updated at Posted at 2022-02-04

reactor-coreのMonoやFluxを使う上で、よくやってしまうリソース解放に関する誤りを、Mono#deferの使い方とともに説明します。
reactor-coreのその他の使い方については、Reactor 3 Reference Guidを参考にして下さい。

前準備

reactor-coreに従って、reactor-coreを使ったJavaプログラミングが出来る環境を準備します。

問題のあるコード

MonoFluxの処理は、subscribeblock等の終端処理が呼ばれた際に実行されます。このため、終端処理が呼ばれるたびに、doOnTerminate等のハンドラーが実行されます。以下のように、Monoの外側で作成したリソースをdoOnTerminatecloseすると、2回目の終端処理の呼び出しはすでにcloseされているリソースに対して実行されてしまいます。

    private static class _SampleCloseable implements Closeable {

        private boolean _closed;

        @Override
        public synchronized void close() {
            // 2回以上、closeが呼ばれるとエラーになる。
            if (_closed) {
                throw new RuntimeException("Already closed.");
            }
            _closed = true;
        }

    }

    @Test
    public void testInvalidClose() throws Exception {
        var closeable = new _SampleCloseable();
        var mono = Mono.just("good").doOnTerminate(() -> {
            closeable.close();
        });
        // 内部でcloseが呼ばれる
        var value = mono.block();
        Assertions.assertEquals("good", value);
        // 内部でcloseが呼ばれる(2回目なのでエラーになる)
        Assertions.assertThrows(RuntimeException.class, () -> mono.block());
    }

deferを使用した修正

deferを使用することで、Monoの内部でリソースの初期化を行う事が出来ます。

    @Test
    public void testDefer() throws Exception {
        var mono = Mono.defer(() -> {
            // リソースの初期化をdefer内で行います。
            var closeable = new _SampleCloseable();
            return Mono.just("good").doOnTerminate(() -> {
                closeable.close();
            });
        });
        // block実行時に、リソースが初期化されて、閉じられます
        var value = mono.block();
        Assertions.assertEquals("good", value);
        // block実行時に、リソースが初期化されて、閉じられます
        value = mono.block();
        Assertions.assertEquals("good", value);
    }

結論

deferを使うことで、リソースの初期化と解放をMonoやFluxに閉じて行う事が出来ます。
MonoFluxの生成と同じスコープでリソースの初期化をしているケースでは、こちらの問題が発生する可能性を常に考慮する必要があります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0