2

Usecase:

There is a module which Listens for events in synchronous mode. In the same module using the EmitterProccessor, the event is converted to Flux and made as infinite stream of events. Now there is a upstream module which can subscribes for these event streams. The problem here is how can I dynamically merge these streams to one and then subscribe in a single stream. A simple example is, let us say there are N number of sensors, we can dynamically register these sensors and start listening for measurements as stream of data in single stream after merging them into one stream. Here is the code sample written to mock this behavior.

Create callback and start listening for events

public interface CallBack {

    void callBack(int name);

    void done();
}

@Slf4j
@RequiredArgsConstructor
public class CallBackService {

    private CallBack callBack;
    private final Function<Integer, Integer> func;

    public void register(CallBack intf) {
        this.callBack = intf;
    }


    public void startServer() {
        log.info("Callback started..");
        IntStream.range(0, 10).forEach(i -> {
            callBack.callBack(func.apply(i));
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        log.info("Callback finished..");
        callBack.done();
    }
}

Convert the events to streams using event proccessor

@Slf4j
public class EmitterService implements CallBack {

    private EmitterProcessor<Integer> emitterProcessor;

    public EmitterService(){
        emitterProcessor = EmitterProcessor.create();
    }

    public EmitterProcessor<Integer> getEmmitor() {
        return emitterProcessor;
    }


    @Override
    public void callBack(int name) {
        log.info("callbakc {} invoked", name);
        //fluxSink.next(name);
        emitterProcessor.onNext(name);
    }

    public void done() {
        //fluxSink.complete();
        emitterProcessor.onComplete();
    }
}


public class WrapperService {

    EmitterService service1;
    ExecutorService service2;

    public Flux<Integer> startService(Function<Integer, Integer> func) {
        CallBackService service = new CallBackService(func);
        service1 = new EmitterService();
        service.register(service1);
        service2 = Executors.newSingleThreadExecutor();
        service2.submit(service::startServer);
        return service1.getEmmitor();
    }

    public void shutDown() {
        service1.getEmmitor().onComplete();
        service2.shutdown();
    }
}

Subscribe for the events

@Slf4j
public class MainService {


    public static void main(String[] args) throws InterruptedException {
        TopicProcessor<Integer> stealer = TopicProcessor.<Integer>builder().share(true).build();
        CountDownLatch latch = new CountDownLatch(20);
        WrapperService n1 =new WrapperService();
        WrapperService n2 =new WrapperService();
//        n1.startService(i->i).mergeWith(n2.startService(i->i*2)).subscribe(stealer);
        n1.startService(i->i).subscribe(stealer);
        n2.startService(i->i*2).subscribe(stealer);
        stealer.subscribeOn(Schedulers.boundedElastic())
                .subscribe(x->{
                    log.info("Stole=>{}", x);
                    latch.countDown();
                    log.info("Latch count=>{}", latch.getCount());
                });

        latch.await();
        n1.shutDown();
        n2.shutDown();
        stealer.shutdown();
    }


}

Tried to use TopicProccessor with no success. In the above code subscription happens for first source, for second source there is no subscription. however if use n1.startService(i->i).mergeWith(n2.startService(i->i*2)).subscribe(stealer); subscription works, but there is no dynamic behavior in this case. Need to change subscriber every time.

halfer
  • 19,824
  • 17
  • 99
  • 186
Karthik Prasad
  • 9,662
  • 10
  • 64
  • 112

0 Answers0