You have probably done some reactive programming, even if you didn’t realise it at that time: - Defining cell values in spreadsheets is similar to defining variables in imperative programming - Defining cell expressions in spreadsheets is similar to defining and operating on reactive types Reactive programming
Previous example in spreadsheet: - assign cell B1 with value of 2 - assign cell B2 with value of 3 - assign cell B3 with an expression that multiplies B1 value with B2 value - when value of either referenced component in the expression changes -> expression is re-evaluated automagically in B3
Dutch computer scientist Erik Meijer @Microsoft: C#, LINQ Reactive Extensions (RX) Currently Director Of Engineering @ Facebook Bearer of extremely cool tie-dyed shirts reactivex.io
Reactive Manifesto To be reactive, according to The Reactive Manifesto, you have to be Responsive, Resilient, Elastic, and Message Driven. The last criteria in this list caused big movement into the asynchronous way of communications.
Goal of Reactive Streams exchange of data across an asynchronous boundary while ensuring that the receiving side is not forced to buffer arbitrary amounts of data (back pressure)
Flux.op1.op2.subscribeOn.op3.op4.subscribe 1 2 SubscribeOn() changes where sequence subscription happens… 1 … which is also where data flows initially 2
java.lang.ArithmeticException: / by zero at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:107) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:115) at reactor.core.publisher.FluxJust$WeakScalarSubscription.request(FluxJust.java:99) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:156) at reactor.core.publisher.BlockingSingleSubscriber.onSubscribe(BlockingSingleSubscriber.java:49) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:70) at reactor.core.publisher.FluxMapFuseable.subscribe(FluxMapFuseable.java:63) at reactor.core.publisher.FluxMapFuseable.subscribe(FluxMapFuseable.java:63) at reactor.core.publisher.Flux.subscribe(Flux.java:6873) at mycode.test(MyTest.java:xx) Debugging
DNS Resolution IP1 IP2 IP3 IP4 SNTP Request 1 NTP POOL Least Roundtrip Delay SNTP Request 2 SNTP Request 3 SNTP Request 4 SNTP Request 5 Statistical analysis Sort by clock offset + median NTP Time Best possible approximation of 5 . . .
DNS Resolution IP1 IP2 IP3 IP4 SNTP Request 1 NTP POOL Least Roundtrip Delay SNTP Request 2 SNTP Request 3 SNTP Request 4 SNTP Request 5 Statistical analysis Sort by clock offset + median NTP Time Best possible approximation of 5 . . .
Reactor is so so… Reactor is not the holy grail. Should be used for streams processing, for general asynchronous non-blocking computation, see coroutines (Spring 5.2+)
Reactor has downsides? Mindshift (also when testing) Debugging & stacktraces are harder For the DDD people: (small) pollution of your domain with Mono/Flux