Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call Sinks.Many<T>.tryEmitNext from multiple threads?

I am wrapping my head around Flux Sinks and cannot understand the higher-level picture. When using Sinks.Many<T> tryEmitNext, the function tells me if there was contention and what should I do in case of failure, (FailFast/Handler).

But is there a simple construct which allows me to safely emit elements from multiple threads. For example, instead of letting the user know that there was contention and I should try again, maybe add elements to a queue(mpmc, mpsc etc), and only notify when the queue is full.

Now I can add a queue myself to alleviate the problem, but it seems a common use case. I guess I am missing a point here.

like image 406
Rahul Kushwaha Avatar asked Nov 26 '20 21:11

Rahul Kushwaha


1 Answers

I hit the same issue, migrating from Processors which support safe emission from multiple threads. I use this custom EmitFailureHandler to do a busy loop as suggested by the EmitFailureHandler docs.

public static EmitFailureHandler etryOnNonSerializedElse(EmitFailureHandler fallback){
    return (signalType, emitResult) -> {
        if (emitResult == EmitResult.FAIL_NON_SERIALIZED) {
            LockSupport.parkNanos(10);
            return true;
        } else
            return fallback.onEmitFailure(signalType, emitResult);
    };
}

There are various confusing aspects about the 3.4.0 implementation

  • There is an implication that unless the Unsafe variant is used, the sink supports serialized emission but actually all the serialized version does is to fail fast in case of concurrent emission.
  • The Sink provided by Flux.Create does support threadsafe emission.

I hope there will be a solidly engineered alternative to this offered by the library at some point.

like image 80
Neil Swingler Avatar answered Sep 17 '22 12:09

Neil Swingler