package com.github.benjchristensen.gist; import rx.Observable; import rx.schedulers.Schedulers; import rx.subjects.PublishSubject; /** * Simple pass-thru event bus with parallel processing of events and error handling. */ public class EventBusWithParallelProcessing { public static void main(String[] args) { MyEventBus bus = new MyEventBus(); // perform IO in parallel for each event bus.toObservable().flatMap(o -> { return Observable.just(o).map(v -> { // simulate latent network call try { Thread.sleep(400); } catch (Exception e) {} return "IO-Response_" + v; }).subscribeOn(Schedulers.io()); }).forEach(result -> System.out.println("IO => " + result)); // perform computation in parallel for each event bus.toObservable().flatMap(o -> { return Observable.just(o).map(v -> { // simulate expensive computation try { Thread.sleep(200); } catch (Exception e) {} return "Computed_" + v; }).subscribeOn(Schedulers.computation()); }).forEach(result -> System.out.println("Computation => " + result)); // perform work for each event that sometimes results in errors bus.toObservable().flatMap(o -> { return Observable.just(o).map(v -> { if(v.equals("hello")) { throw new RuntimeException("Simulated error processing -> " + v); } return "Processed_" + v; }).onErrorResumeNext(Observable.just("DefaultValueFor_" + o)).subscribeOn(Schedulers.computation()); }).forEach(result -> System.out.println("Processed => " + result)); bus.send(1); bus.send(11); bus.send(28); bus.send("hello"); bus.send(5); bus.send("world"); // Since we're doing work asynchronously above we need to wait on it // (There are other more "idiomatic" ways of doing this without sleeping // but they require changing to ReplaySubject or using CountdownLatches. I // chose to stay simple and obvious for this and leave the rest of the code // as intended for the example). try { Thread.sleep(2000); } catch (Exception e) {} } public static boolean IS_NUMBER(Object o) { if (o instanceof Number) { return true; } else { return false; } } public static boolean IS_STRING(Object o) { if (o instanceof String) { return true; } else { return false; } } public static class MyEventBus { private final PublishSubject<Object> bus = PublishSubject.create(); /** * If multiple threads are going to emit events to this then it must be made thread-safe like this instead: */ // private final Subject<Object, Object> bus = new SerializedSubject<Object, Object>(PublishSubject.create()); public void send(Object o) { bus.onNext(o); } public Observable<Object> toObservable() { return bus; } } }