Let's say I have such a method in class implementing BeforeConvertCall<Object>
@Override
public Publisher<Object> onBeforeConvert(Object o, SqlIdentifier sqlIdentifier) {
return Mono.fromCallable(() -> enhance(o)); (A)
//
return Mono.just(o)
.map(this::enhance); (B)
}
private Object enhance(Object o) {
if (o instanceof Foo && ((Foo) o).getId() == null) {
((Foo) o).setId(UUID.randomUUID().toString());
}
return o;
}
- Is this code blocking? I mean should one be concerned?
- Does it make sense to wrap
UUID
generation byThreadLocal
in reactor? - Is there any difference between (A) and (B) calls?
I tried also put inside a enhance method this time-consuming operation:
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String id = UUID.randomUUID().toString();
}
and made 3 concurrent requests.
4 reactor-http-nio
threads were spawned all in the runnable state. First did lock SecureRandom
and rest 3:
- locked <0x0000000600c4b510> (a io.netty.channel.nio.SelectedSelectionKeySet)
- locked <0x0000000600c4b4b0> (a sun.nio.ch.KQueueSelectorImpl)
- Why the rest 3 threads were not blocked because of the lock on the
SecureRandom
instance?
I tried to place the same for cycle into main pipeline within doNext()
hook and there suddenly rest threads got blocked as expected.
- Why did they get blocked here but with the same approach within the
onBeforeConvert()
they did not? Moreover, when I tried to wrap the call with theThreadLocal
, it did not help.
java.lang.Thread.State: BLOCKED (on object monitor) at sun.security.provider.SecureRandom.engineNextBytes(java.base@11.0.10/SecureRandom.java:216)
- waiting to lock <0x0000000600118b28> (a sun.security.provider.SecureRandom)
- I would expect to all 4 threads have own instance of
SecureRandom
.. or not? Is it perhaps so that only main thread own the instance and it populates work to the working threads which have no thread-local ofSecureRandom
?
Last one experiment:
@Override
public Publisher<Object> onBeforeConvert(Object o, SqlIdentifier sqlIdentifier) {
return Mono.fromCallable(() -> enhance(o))
.map(this::enhance)
.subscribeOn(Schedulers.boundedElastic()); (C)
}
After adding line (C) and running 4 concurrent requests, boundedElastic-2
,3,4 did get blocked.
- Why did they get blocked though
reactor-http-nio
in the previous approach did not get blocked?