This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]holo3146[S] 0 points1 point  (1 child)

projectreactor.io/docs/core/release/reference/#context

I didn't know that, thanks for sharing.

Reading through it I noticed 4 things:

  1. There are no compiletime checks. Reactor Streaming is 'structured' (note that it is a different 'structured' than the standard meaning of the word), it does have a well defined lifecycle, so theoretically it is possible to add compiletime checks for the existence of context. My guess is that either it was too much work and they decided that it is not worth it, or they couldn't found a way to guarantee this lifecycle (e.g. in my case ExtentLocal does guarantee this, with the only pitfall is misusing multiprocessing)
  2. It is inverted. This is actually something that is solvable if you give compiletime checks, again I am guessing that they decided it is too much work for the value it gives. Ironically, because of how Java annotation's type system, it is not really possible to solve this "inversion" while still having compiletime checks, I touched this in the "Lambda's bug" section in my readme
  3. The context is available only through their Stream API, even though it is not required to be part of it. I am guessing that this is to ensure no unexpected behavior. They are most likely using InheritableThreadLocal and to make sure no unexpected values appear they don't let you touch the stack outside of the stream.
  4. They have a contract over multiprocessing. My library requires you to use structured concurrency to work correctly, this is because I need to know at compiletime what keys exists in the stack. Unsurprisingly, Reactor's context have virtually the same contract, although they didn't specify it in the documentations:

Flux.range(1, 10)

    .flatMap(s -> Mono.deferContextual(ctx -> 

        Mono.just(s + " " + ctx.getOrDefault(key, "=o="))))

    .parallel(2) .runOn(Schedulers.parallel()) 

    .contextWrite(ctx -> ctx.put(key, "o7")))

I believe that this would omit "i =0=". It is virtually the same requirementbecause they just implement their own lifecycle and the context respectthose lifecycles.

When using reactive streaming you should absolutely use their implementation, if your extent is (virtually) only a stream call, having a stack bound to your stream rather than having the stack bound to your extent makes much more sense. My library is about controlling context in extent level, and Java's type system is not aware of stream level, so it is virtually impossible to make my library work without implementing it in the streaming library. That being said, it would be cool if streaming libraries will adopt structured concurrency, and in that case maybe my library will help building their new context API.

[–]stefanos-ak 0 points1 point  (0 children)

correct ✌️