[
  {
    "path": ".gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\n### Java template\n*.class\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\ntarget\n\n.idea\n*.iml"
  },
  {
    "path": "README.md",
    "content": "# RxJava 2.x\n\nView at [Github page](https://balamaci.github.io/rxjava-walkthrough/)\n\nalso available for [reactor-core](https://github.com/balamaci/reactor-core-playground) \n\n## Contents \n \n   - [Flowable, Single and Observable](#flowable)\n   - [Simple Operators](#simple-operators)\n   - [Merging Streams](#merging-streams)\n   - [Hot Publishers](#hot-publishers)\n   - [Schedulers](#schedulers)\n   - [FlatMap Operator](#flatmap-operator)\n   - [Error Handling](#error-handling)\n   - [Backpressure](#backpressure)\n   - [Articles and books](#articles)\n\n## Reactive Streams\nReactive Streams is a programming concept for handling asynchronous \ndata streams in a non-blocking manner while providing backpressure to stream publishers.\nIt has evolved into a [specification](https://github.com/reactive-streams/reactive-streams-jvm) that is based on the concept of **Publisher&lt;T&gt;** and **Subscriber&lt;T&gt;**.\nA **Publisher** is the source of events **T** in the stream, and a **Subscriber** is the consumer for those events.\nA **Subscriber** subscribes to a **Publisher** by invoking a \"factory method\" in the Publisher that will push\nthe stream items **&lt;T&gt;** starting a new **Subscription**:\n\n```java\npublic interface Publisher<T> {\n    public void subscribe(Subscriber<? super T> s);\n}\n```\n\nWhen the Subscriber is ready to start handling events, it signals this via a **request** to that **Subscription**\n \n```java\npublic interface Subscription {\n    public void request(long n); //request n items\n    public void cancel();\n}\n```\n\nUpon receiving this signal, the Publisher begins to invoke **Subscriber::onNext(T)** for each event **T**. \nThis continues until either completion of the stream (**Subscriber::onComplete()**) \nor an error occurs during processing (**Subscriber::onError(Throwable)**).\n\n```java\npublic interface Subscriber<T> {\n    //signals to the Publisher to start sending events\n    public void onSubscribe(Subscription s);     \n    \n    public void onNext(T t);\n    public void onError(Throwable t);\n    public void onComplete();\n}\n```\n\n## Flowable and Observable\nRxJava provides more types of event publishers: \n   - **Flowable** Publisher that emits 0..N elements, and then completes successfully or with an error\n   - **Observable** like Flowables but without a backpressure strategy. They were introduced in RxJava 1.x\n   \n   - **Single** a specialized emitter that completes with a value successfully either an error.(doesn't have onComplete callback, instead onSuccess(val))\n   - **Maybe** a specialized emitter that can complete with / without a value or complete with an error.\n   - **Completable** a specialized emitter that just signals if it completed successfully or with an error.\n\nCode is available at [Part01CreateFlowable.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part01CreateFlowable.java)\n\n### Simple operators to create Streams\n```java\nFlowable<Integer> flowable = Flowable.just(1, 5, 10);\nFlowable<Integer> flowable = Flowable.range(1, 10);\nFlowable<String> flowable = Flowable.fromArray(new String[] {\"red\", \"green\", \"blue\"});\nFlowable<String> flowable = Flowable.fromIterable(List.of(\"red\", \"green\", \"blue\"));\n```\n\n\n### Flowable from Future\n\n```java\nCompletableFuture<String> completableFuture = CompletableFuture\n            .supplyAsync(() -> { //starts a background thread the ForkJoin common pool\n                    log.info(\"CompletableFuture work starts\");  \n                    Helpers.sleepMillis(100);\n                    return \"red\";\n            });\n\nSingle<String> single = Single.from(completableFuture);\nsingle.subscribe(val -> log.info(\"Stream completed successfully : {}\", val));\n```\n\n\n### Creating your own stream\n\nWe can use **Flowable.create(...)** to implement the emissions of events by calling **onNext(val)**, **onComplete()**, **onError(throwable)**\n\nWhen subscribing to the Observable / Flowable with flowable.subscribe(...) the lambda code inside **create(...)** gets executed.\nFlowable.subscribe(...) can take 3 handlers for each type of event - onNext, onError and onCompleted.\n\nWhen using **Observable.create(...)** you need to be aware of [backpressure](#backpressure) and that Observables created with 'create' are not BackPressure aware\n\n```java \nObservable<Integer> stream = Observable.create(subscriber -> {\n    log.info(\"Started emitting\");\n\n    log.info(\"Emitting 1st\");\n    subscriber.onNext(1);\n\n    log.info(\"Emitting 2nd\");\n    subscriber.onNext(2);\n\n    subscriber.onComplete();\n});\n\n//Flowable version same Observable but with a BackpressureStrategy\n//that will be discussed separately.\nFlowable<Integer> stream = Flowable.create(subscriber -> {\n    log.info(\"Started emitting\");\n\n    log.info(\"Emitting 1st\");\n    subscriber.onNext(1);\n\n    log.info(\"Emitting 2nd\");\n    subscriber.onNext(2);\n\n    subscriber.onComplete();\n}, BackpressureStrategy.MISSING);\n\nstream.subscribe(\n       val -> log.info(\"Subscriber received: {}\", val),\n       err -> log.error(\"Subscriber received error\", err),\n       () -> log.info(\"Subscriber got Completed event\")\n);\n```\n\n### Streams are lazy \nStreams are lazy meaning that the code inside create() doesn't get executed without subscribing to the stream.\nSo event if we sleep for a long time inside create() method(to simulate a costly operation),\nwithout subscribing to this Observable, the code is not executed and the method returns immediately.\n\n```java\npublic void observablesAreLazy() {\n    Observable<Integer> observable = Observable.create(subscriber -> {\n        log.info(\"Started emitting but sleeping for 5 secs\"); //this is not executed\n        Helpers.sleepMillis(5000);\n        subscriber.onNext(1);\n    });\n    log.info(\"Finished\"); \n}\n===========\n[main] - Finished\n```\n\n### Multiple subscriptions to the same Observable / Flowable \nWhen subscribing to an Observable/Flowable, the create() method gets executed for each Subscriber, the events \ninside **create(..)** are re-emitted to each subscriber independently. \n\nSo every subscriber will get the same events and will not lose any events - this behavior is named **'cold observable'**\nSee [Hot Publishers](#hot-publisher) to understand sharing a subscription and multicasting events.\n \n```java\nObservable<Integer> observable = Observable.create(subscriber -> {\n   log.info(\"Started emitting\");\n\n   log.info(\"Emitting 1st event\");\n   subscriber.onNext(1);\n\n   log.info(\"Emitting 2nd event\");\n   subscriber.onNext(2);\n\n   subscriber.onComplete();\n});\n\nlog.info(\"Subscribing 1st subscriber\");\nobservable.subscribe(val -> log.info(\"First Subscriber received: {}\", val));\n\nlog.info(\"=======================\");\n\nlog.info(\"Subscribing 2nd subscriber\");\nobservable.subscribe(val -> log.info(\"Second Subscriber received: {}\", val));\n```\n\nwill output\n\n```\n[main] - Subscribing 1st subscriber\n[main] - Started emitting\n[main] - Emitting 1st event\n[main] - First Subscriber received: 1\n[main] - Emitting 2nd event\n[main] - First Subscriber received: 2\n[main] - =======================\n[main] - Subscribing 2nd subscriber\n[main] - Started emitting\n[main] - Emitting 1st event\n[main] - Second Subscriber received: 1\n[main] - Emitting 2nd event\n[main] - Second Subscriber received: 2\n```\n\n## Observable / Flowable lifecycle\n\n### Operators\nBetween the source Observable / Flowable and the Subscriber there can be a wide range of operators and RxJava provides \nlots of operators to chose from. Probably you are already familiar with functional operations like **filter** and **map**. \nso let's use them as example:\n\n```java\nFlowable<Integer> stream = Flowable.create(subscriber -> {\n        subscriber.onNext(1);\n        subscriber.onNext(2);\n        ....\n        subscriber.onComplete();\n    }, BackpressureStrategy.MISSING);\n    .filter(val -> val < 10)\n    .map(val -> val * 10)\n    .subscribe(val -> log.info(\"Received: {}\", val));\n```\n\nWhen we call _Flowable.create()_ you might think that we're calling onNext(..), onComplete(..) on the Subscriber at the end of the chain, \nnot the operators between them.\n\nThis is not true because **the operators themselves are decorators for their source** wrapping it with the operator behavior \nlike an onion's layers. \nWhen we call **.subscribe()** at the end of the chain, **Subscription propagates through the layers back to the source,\neach operator subscribing itself to it's wrapped source Observable / Flowable and so on to the original source, \ntriggering it to start producing/emitting items**.\n\n**Flowable.create** calls **---&gt; filterOperator.onNext(val)** which if val &gt; 10 calls **---&gt; \nmapOperator.onNext(val)** does val = val * 10 and calls **---&gt; subscriber.onNext(val)**. \n\n[Found](https://tomstechnicalblog.blogspot.ro/2015_10_01_archive.html) a nice analogy with a team of house movers, with every mover doing it's thing before passing it to the next in line \nuntil it reaches the final subscriber.\n\n![Movers](https://1.bp.blogspot.com/-1RuGVz4-U9Q/VjT0AsfiiUI/AAAAAAAAAKQ/xWQaOwNtS7o/s1600/animation_2.gif) \n \n### Canceling subscription\nInside the create() method, we can check is there are still active subscribers to our Flowable/Observable.\n\nThere are operators that also unsubscribe from the stream so the source knows to stop producing events.  \nIt's a way to prevent to do extra work(like for ex. querying a datasource for entries) if no one is listening\nIn the following example we'd expect to have an infinite stream, but because we stop if there are no active subscribers, we stop producing events.   \n\n**take(limit)** is a simple operator. It's role is to count the number of events and then unsubscribes from it's source \nonce it received the specified amount and calls onComplete() to it's subscriber.\n\n```java\nObservable<Integer> observable = Observable.create(subscriber -> {\n\n    int i = 1;\n    while(true) {\n        if(subscriber.isDisposed()) {\n             break;\n        }\n\n        subscriber.onNext(i++);\n        \n        //registering a callback when the downstream subscriber unsubscribes\n        subscriber.setCancellable(() -> log.info(\"Subscription canceled\"));\n    }\n});\n\nobservable\n    .take(5) //unsubscribes after the 5th event\n    .subscribe(val -> log.info(\"Subscriber received: {}\", val),\n               err -> log.error(\"Subscriber received error\", err),\n               () -> log.info(\"Subscriber got Completed event\") //The Complete event \n               //is triggered by 'take()' operator\n\n==================\n[main] - Subscriber received: *1*\n[main] - Subscriber received: *2*\n[main] - Subscriber received: *3*\n[main] - Subscriber received: *4*\n[main] - Subscriber received: *5*\n[main] - Subscriber got Completed event\n[main] - Subscription canceled\n```\n\n\n## Simple Operators\nCode is available at [Part02SimpleOperators.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part02SimpleOperators.java)\n\n### delay\nDelay operator - the Thread.sleep of the reactive world, it's pausing each emission for a particular increment of time.\n\n```java\nCountDownLatch latch = new CountDownLatch(1);\nFlowable.range(0, 2)\n        .doOnNext(val -> log.info(\"Emitted {}\", val))\n        .delay(5, TimeUnit.SECONDS)\n        .subscribe(tick -> log.info(\"Tick {}\", tick),\n                   (ex) -> log.info(\"Error emitted\"),\n                   () -> {\n                          log.info(\"Completed\");\n                          latch.countDown();\n                   });\nlatch.await();\n\n==============\n14:27:44 [main] - Starting\n14:27:45 [main] - Emitted 0\n14:27:45 [main] - Emitted 1\n14:27:50 [RxComputationThreadPool-1] - Tick 0\n14:27:50 [RxComputationThreadPool-1] - Tick 1\n14:27:50 [RxComputationThreadPool-1] - Completed\n```\n\nThe **.delay()**, **.interval()** operators uses a [Scheduler](#schedulers) by default which is why we see it executing\non a different thread _RxComputationThreadPool-1_ which actually means it's running the operators and the subscribe operations \non another thread and so the test method will terminate before we see the text from the log unless we wait for the completion of the stream. \nThis is the role of the **CountdownLatch**.\n\n### interval\nPeriodically emits a number starting from 0 and then increasing the value on each emission.\n\n```java\nlog.info(\"Starting\");\nFlowable.interval(5, TimeUnit.SECONDS)\n       .take(4)\n       .subscribe(tick -> log.info(\"Subscriber received {}\", tick),\n                  (ex) -> log.info(\"Error emitted\"),\n                  () -> log.info(\"Subscriber got Completed event\"));\n\n==========\n12:17:56 [main] - Starting\n12:18:01 [RxComputationThreadPool-1] - Subscriber received: 0\n12:18:06 [RxComputationThreadPool-1] - Subscriber received: 1\n12:18:11 [RxComputationThreadPool-1] - Subscriber received: 2\n12:18:16 [RxComputationThreadPool-1] - Subscriber received: 3\n12:18:21 [RxComputationThreadPool-1] - Subscriber received: 4\n12:18:21 [RxComputationThreadPool-1] - Subscriber got Completed event\n```\n\n\n\n### scan\nTakes an **initial value** and a **function(accumulator, currentValue)**. It goes through the events\nsequence and combines the current event value with the previous result(accumulator) emitting downstream the function's\nresult for each event(the initial value is used for the first event)\n\n```java\nFlowable<Integer> numbers = \n                Flowable.just(3, 5, -2, 9)\n                    .scan(0, (totalSoFar, currentValue) -> {\n                               log.info(\"TotalSoFar={}, currentValue={}\", \n                                            totalSoFar, currentValue);\n                               return totalSoFar + currentValue;\n                    });\n\n=============\n16:09:17 [main] - Subscriber received: 0\n16:09:17 [main] - TotalSoFar=0, currentValue=3\n16:09:17 [main] - Subscriber received: 3\n16:09:17 [main] - TotalSoFar=3, currentValue=5\n16:09:17 [main] - Subscriber received: 8\n16:09:17 [main] - TotalSoFar=8, currentValue=-2\n16:09:17 [main] - Subscriber received: 6\n16:09:17 [main] - TotalSoFar=6, currentValue=9\n16:09:17 [main] - Subscriber received: 15\n16:09:17 [main] - Subscriber got Completed event\n```\n\n### reduce\nreduce operator acts like the scan operator but it only passes downstream the final result \n(doesn't pass the intermediate results downstream) so the subscriber receives just one event\n\n```java\nFlowable<Integer> numbers = Flowable.just(3, 5, -2, 9)\n                            .reduce(0, (totalSoFar, val) -> {\n                                         log.info(\"totalSoFar={}, emitted={}\",\n                                                        totalSoFar, val);\n                                         return totalSoFar + val;\n                            });\n                            \n=============                            \n17:08:29 [main] - totalSoFar=0, emitted=3\n17:08:29 [main] - totalSoFar=3, emitted=5\n17:08:29 [main] - totalSoFar=8, emitted=-2\n17:08:29 [main] - totalSoFar=6, emitted=9\n17:08:29 [main] - Subscriber received: 15\n17:08:29 [main] - Subscriber got Completed event\n```\n\n### collect\ncollect operator acts similar to the _reduce_ operator, but while the _reduce_ operator uses a reduce function\nwhich returns a value, the _collect_ operator takes a container supplier and a function which doesn't return\nanything(a consumer). The mutable container is passed for every event and thus you get a chance to modify it\nin this collect consumer function.\n\n```java\nFlowable<List<Integer>> numbers = Flowable.just(3, 5, -2, 9)\n                                        .collect(ArrayList::new, (container, value) -> {\n                                            log.info(\"Adding {} to container\", value);\n                                            container.add(value);\n                                            //notice we don't need to return anything\n                                        });\n=========\n17:40:18 [main] - Adding 3 to container\n17:40:18 [main] - Adding 5 to container\n17:40:18 [main] - Adding -2 to container\n17:40:18 [main] - Adding 9 to container\n17:40:18 [main] - Subscriber received: [3, 5, -2, 9]\n17:40:18 [main] - Subscriber got Completed event\n```\n\nbecause the usecase to store to a List container is so common, there is a **.toList()** operator that is just a collector adding to a List. \n\n### defer\nAn easy way to switch from a blocking method to a reactive Single/Flowable is to use **.defer(() -> blockingOp())**.\n\nSimply using **Flowable.just(blockingOp())** would still block, as Java needs to resolve the parameter when invoking\n**Flux.just(param)** method, so _blockingOp()_ method would still be invoked(and block).\n\n```java\n//NOT OK\nFlowable<String> flowableBlocked = Flowable.just((blockingOp())); //blocks on this line\n```\n    \nIn order to get around this problem, we can use **Flowable.defer(() -> blockingOp())** and wrap the _blockingOp()_ call inside a lambda which \nwill be invoked lazy **at subscribe time**.\n\n```java\nFlowable<String> stream = Flowable.defer(() -> Flowable.just(blockingOperation())); \nstream.subscribe(val -> log.info(\"Val \" + val)); //only now the code inside defer() is executed\n```\n\n\n## Merging Streams\nOperators for working with multiple streams\nCode at [Part03MergingStreams.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part03MergingStreams.java)\n\n### zip\nZip operator operates sort of like a zipper in the sense that it takes an event from one stream and waits\nfor an event from another other stream. Once an event for the other stream arrives, it uses the zip function\nto merge the two events.\n\nThis is an useful scenario when for example you want to make requests to remote services in parallel and\nwait for both responses before continuing. It also takes a function which will produce the combined result\nof the zipped streams once each has emitted a value.\n\n![Zip](https://raw.githubusercontent.com/reactor/projectreactor.io/master/src/main/static/assets/img/marble/zip.png)\n\nZip operator besides the streams to zip, also takes as parameter a function which will produce the \ncombined result of the zipped streams once each stream emitted its value\n\n```java\nSingle<Boolean> isUserBlockedStream = \n                    Single.fromFuture(CompletableFuture.supplyAsync(() -> {\n                            Helpers.sleepMillis(200);\n                            return Boolean.FALSE;\n                    }));\n\nSingle<Integer> userCreditScoreStream = \n                    Single.fromFuture(CompletableFuture.supplyAsync(() -> {\n                            Helpers.sleepMillis(2300);\n                            return 5;\n                    }));\n\nSingle<Pair<Boolean, Integer>> userCheckStream = Single.zip(isUserBlockedStream, userCreditScoreStream, \n                      (blocked, creditScore) -> new Pair<Boolean, Integer>(blocked, creditScore));\n\nuserCheckStream.subscribe(pair -> log.info(\"Received \" + pair));\n```\n\nEven if the 'isUserBlockedStream' finishes after 200ms, 'userCreditScoreStream' is slow at 2.3secs, \nthe 'zip' method applies the combining function(new Pair(x,y)) after it received both values and passes it \nto the subscriber.\n\n\nAnother good example of 'zip' is to slow down a stream by another basically **implementing a periodic emitter of events**:\n\n```java  \nFlowable<String> colors = Flowable.just(\"red\", \"green\", \"blue\");\nFlowable<Long> timer = Flowable.interval(2, TimeUnit.SECONDS);\n\nFlowable<String> periodicEmitter = Flowable.zip(colors, timer, (key, val) -> key);\n```\n\nSince the zip operator needs a pair of events, the slow stream will work like a timer by periodically emitting \nwith zip setting the pace of emissions downstream every 2 seconds.\n\n**Zip is not limited to just two streams**, it can merge 2,3,4,.. streams and wait for groups of 2,3,4 'pairs' of \nevents which it combines with the zip function and sends downstream.\n\n### merge\nMerge operator combines one or more stream and passes events downstream as soon as they appear.\n\n![merge](https://raw.githubusercontent.com/reactor/projectreactor.io/master/src/main/static/assets/img/marble/merge.png)\n\n```\nFlowable<String> colors = periodicEmitter(\"red\", \"green\", \"blue\", 2, TimeUnit.SECONDS);\n\nFlowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS)\n                .take(5);\n                \n//notice we can't say Flowable<String> or Flowable<Long> as the return stream o the merge operator since \n//it can emit either a color or number.                  \nFlowable flowable = Flowable.merge(colors, numbers);                \n\n============\n21:32:15 - Subscriber received: 0\n21:32:16 - Subscriber received: red\n21:32:16 - Subscriber received: 1\n21:32:17 - Subscriber received: 2\n21:32:18 - Subscriber received: green\n21:32:18 - Subscriber received: 3\n21:32:19 - Subscriber received: 4\n21:32:20 - Subscriber received: blue\n```\n\n### concat\nConcat operator appends another streams at the end of another\n![concat](https://raw.githubusercontent.com/reactor/projectreactor.io/master/src/main/static/assets/img/marble/concat.png)\n\n```java\nFlowable<String> colors = periodicEmitter(\"red\", \"green\", \"blue\", 2, TimeUnit.SECONDS);\n\nFlowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS)\n                .take(4);\n\nFlowable events = Flowable.concat(colors, numbers);\n\n==========\n22:48:23 - Subscriber received: red\n22:48:25 - Subscriber received: green\n22:48:27 - Subscriber received: blue\n22:48:28 - Subscriber received: 0\n22:48:29 - Subscriber received: 1\n22:48:30 - Subscriber received: 2\n22:48:31 - Subscriber received: 3\n```\n\nEven if the 'numbers' streams should start early, the 'colors' stream emits fully its events\nbefore we see any 'numbers'.\nThis is because 'numbers' stream is actually subscribed only after the 'colors' complete.\nShould the second stream be a 'hot' emitter, its events would be lost until the first one finishes\nand the seconds stream is subscribed.\n\n## Hot Publishers\nWe've seen that with 'cold publishers', whenever a subscriber subscribes, each subscriber will get\nit's version of emitted values independently, the exact set of data indifferently when they subscribe.\nBut cold publishers only produce data when the subscribers subscribes, however there are cases where \nthe events happen independently from the consumers regardless if someone is \nlistening or not and we don't have control to request more. So you could say we have 'cold publishers' for pull\nscenarios and 'hot publishers' which push.\n\n### Subjects\nSubjects are one way to handle hot observables. Subjects keep reference to their subscribers and allow 'multicasting' \nan event to them.\n\n```java\nfor (Disposable<T> s : subscribers.get()) {\n    s.onNext(t);\n}\n```\n\nSubjects besides being traditional Observables you can use the same operators and subscribe to them,\nare also an **Observer**(interface like **Subscriber** from [reactive-streams](#reactive-streams), implementing the 3 methods **onNext, onError, onComplete**), \nmeaning you can invoke subject.onNext(value) from different parts in the code,\nwhich means that you publish events which the Subject will pass on to their subscribers.\n\n```java\nSubject<Integer> subject = ReplaySubject.create()\n                     .map(...);\n                     .subscribe(); //\n\n...\nsubject.onNext(val);\n...\nsubject.onNext(val2);\n```\nremember for \n```java\nObservable.create(subscriber -> {\n      subscriber.onNext(val);\n})\n```\n\n### ReplaySubject\nReplaySubject keeps a buffer of events that it 'replays' to each new subscriber, first he receives a batch of missed \nand only later events in real-time.\n\n```java\nSubject<Integer> subject = ReplaySubject.createWithSize(50);\n\nlog.info(\"Pushing 0\");\nsubject.onNext(0);\nlog.info(\"Pushing 1\");\nsubject.onNext(1);\n\nlog.info(\"Subscribing 1st\");\nsubject.subscribe(val -> log.info(\"Subscriber1 received {}\", val), \n                            logError(), logComplete());\n\nlog.info(\"Pushing 2\");\nsubject.onNext(2);\n\nlog.info(\"Subscribing 2nd\");\nsubject.subscribe(val -> log.info(\"Subscriber2 received {}\", val), \n                            logError(), logComplete());\n\nlog.info(\"Pushing 3\");\nsubject.onNext(3);\n\nsubject.onComplete();\n\n==================\n[main] - Pushing 0\n[main] - Pushing 1\n[main] - Subscribing 1st\n[main] - Subscriber1 received 0\n[main] - Subscriber1 received 1\n[main] - Pushing 2\n[main] - Subscriber1 received 2\n[main] - Subscribing 2nd\n[main] - Subscriber2 received 0\n[main] - Subscriber2 received 1\n[main] - Subscriber2 received 2\n[main] - Pushing 3\n[main] - Subscriber1 received 3\n[main] - Subscriber2 received 3\n[main] - Subscriber got Completed event\n[main] - Subscriber got Completed event\n```\n\n### ConnectableObservable / ConnectableFlowable and resource sharing\nThere are cases when we want to share a single subscription between subscribers, meaning while the code that executes\non subscribing should be executed once, the events should be published to all subscribers.     \n\nFor ex. when we want to share a connection between multiple Observables / Flowables. \nUsing a plain Observable would just reexecute the code inside _.create()_ and opening / closing a new connection for each \nnew subscriber when it subscribes / cancels its subscription.\n\n**ConnectableObservable** are a special kind of **Observable**. No matter how many Subscribers subscribe to ConnectableObservable, \nit opens just one subscription to the Observable from which it was created.\n\nAnyone who subscribes to **ConnectableObservable** is placed in a set of Subscribers(it doesn't trigger\nthe _.create()_ code a normal Observable would when .subscribe() is called). A **.connect()** method is available for ConnectableObservable.\n**As long as connect() is not called, these Subscribers are put on hold, they never directly subscribe to upstream Observable**\n\n```java\nConnectableObservable<Integer> connectableObservable = \n                                  Observable.<Integer>create(subscriber -> {\n        log.info(\"Inside create()\");\n\n     /* A JMS connection listener example\n         Just an example of a costly operation that is better to be shared **/\n\n     /* Connection connection = connectionFactory.createConnection();\n        Session session = connection.createSession(true, AUTO_ACKNOWLEDGE);\n        MessageConsumer consumer = session.createConsumer(orders);\n        consumer.setMessageListener(subscriber::onNext); */\n\n        subscriber.setCancellable(() -> log.info(\"Subscription cancelled\"));\n\n        log.info(\"Emitting 1\");\n        subscriber.onNext(1);\n\n        log.info(\"Emitting 2\");\n        subscriber.onNext(2);\n\n        subscriber.onComplete();\n}).publish();\n\nconnectableObservable\n       .take(1)\n       .subscribe((val) -> log.info(\"Subscriber1 received: {}\", val), \n                    logError(), logComplete());\n\nconnectableObservable\n       .subscribe((val) -> log.info(\"Subscriber2 received: {}\", val), \n                    logError(), logComplete());\n\nlog.info(\"Now connecting to the ConnectableObservable\");\nconnectableObservable.connect();\n\n===================\n\n```\n\n### share() operator \nAnother operator of the ConnectableObservable **.refCount()** allows to do away with having to manually call **.connect()**,\ninstead it invokes the .create() code when the first Subscriber subscribes while sharing this single subscription with subsequent Subscribers.\nThis means that **.refCount()** basically keeps a count of references of it's subscribers and subscribes to upstream Observable\n(executes the code inside .create() just for the first subscriber), but multicasts the same event to each active subscriber. \nWhen the last subscriber unsubscribes, the ref counter goes from 1 to 0 and triggers any unsubscribe callback associated.   \nIf another Subscriber subscribes after that, counter goes from 0 to 1 and the process starts over again. \n\n```java\nConnectableObservable<Integer> connectableStream = Observable.<Integer>create(subscriber -> {\n   log.info(\"Inside create()\");\n   \n   //Simulated MessageListener emits periodically every 500 milliseconds\n   ResourceConnectionHandler resourceConnectionHandler = new ResourceConnectionHandler() {\n        @Override\n        public void onMessage(Integer message) {\n             log.info(\"Emitting {}\", message);\n             subscriber.onNext(message);\n        }\n   };\n   resourceConnectionHandler.openConnection();\n\n   //when the last subscriber unsubscribes it will invoke disconnect on the resourceConnectionHandler\n   subscriber.setCancellable(resourceConnectionHandler::disconnect);\n}).publish(); \n\n//publish().refCount() have been joined together in the .share() operator\nObservable<Integer> observable = connectableObservable.refCount();\n\nCountDownLatch latch = new CountDownLatch(2);\nconnectableStream\n      .take(5)\n      .subscribe((val) -> log.info(\"Subscriber1 received: {}\", val), \n                    logError(), logComplete(latch));\n\nHelpers.sleepMillis(1000);\n\nlog.info(\"Subscribing 2nd\");\n//we're not seing the code inside .create() reexecuted\nconnectableStream\n      .take(2)\n      .subscribe((val) -> log.info(\"Subscriber2 received: {}\", val), \n                    logError(), logComplete(latch));\n\n//waiting for the streams to complete\nHelpers.wait(latch);\n\n//subscribing another after previous Subscribers unsubscribed\nlatch = new CountDownLatch(1);\nlog.info(\"Subscribing 3rd\");\nobservable\n     .take(1)\n     .subscribe((val) -> log.info(\"Subscriber3 received: {}\", val), logError(), logComplete(latch));\n\n\nprivate abstract class ResourceConnectionHandler {\n\n   ScheduledExecutorService scheduledExecutorService;\n\n   private int counter;\n\n   public void openConnection() {\n      log.info(\"**Opening connection\");\n\n      scheduledExecutorService = periodicEventEmitter(() -> {\n            counter ++;\n            onMessage(counter);\n      }, 500, TimeUnit.MILLISECONDS);\n   }\n\n   public abstract void onMessage(Integer message);\n\n   public void disconnect() {\n      log.info(\"**Shutting down connection\");\n      scheduledExecutorService.shutdown();\n   }\n}\n\n===============\n14:55:23 [main] INFO BaseTestObservables - Inside create()\n14:55:23 [main] INFO BaseTestObservables - **Opening connection\n14:55:23 [pool-1-thread-1] INFO BaseTestObservables - Emitting 1\n14:55:23 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 1\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Emitting 2\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 2\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Emitting 3\n14:55:24 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 3\n14:55:24 [main] INFO BaseTestObservables - Subscribing 2nd\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Emitting 4\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 4\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber2 received: 4\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Emitting 5\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber1 received: 5\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber got Completed event\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber2 received: 5\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - **Shutting down connection\n14:55:25 [pool-1-thread-1] INFO BaseTestObservables - Subscriber got Completed event\n14:55:25 [main] INFO BaseTestObservables - Subscribing 3rd\n14:55:25 [main] INFO BaseTestObservables - Inside create()\n14:55:25 [main] INFO BaseTestObservables - **Opening connection\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - Emitting 1\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - Subscriber3 received: 1\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - **Shutting down connection\n14:55:25 [pool-2-thread-1] INFO BaseTestObservables - Subscriber got Completed event\n```\nThe **share()** operator of Observable / Flowable is an operator which basically does **publish().refCount()**. \n\n## Schedulers\nRxJava provides some high level concepts for concurrent execution, like ExecutorService we're not dealing\nwith the low level constructs like creating the Threads ourselves. Instead we're using a **Scheduler** which create\nWorkers who are responsible for scheduling and running code. By default RxJava will not introduce concurrency \nand will run the operations on the subscription thread.\n\nThere are two methods through which we can introduce Schedulers into our chain of operations:\n\n   - **subscribeOn** allows to specify which Scheduler invokes the code contained in the lambda code for Observable.create()\n   - **observeOn** allows control to which Scheduler executes the code in the downstream operators\n\nRxJava provides some general use Schedulers:\n \n  - **Schedulers.computation()** - to be used for CPU intensive tasks. A threadpool. Should not be used for tasks involving blocking IO.\n  - **Schedulers.io()** - to be used for IO bound tasks  \n  - **Schedulers.from(Executor)** - custom ExecutorService\n  - **Schedulers.newThread()** - always creates a new thread when a worker is needed. Since it's not thread pooled and \n  always creates a new thread instead of reusing one, this scheduler is not very useful \n \nAlthough we said by default RxJava doesn't introduce concurrency. Notice how we are not doing anything on another thread\nthan the subscribing thread 'main' and the Test doesn't end until the complete event is processed:\n```java\n@Test\npublic void byDefaultRxJavaDoesntIntroduceConcurrency() {\n   log.info(\"Starting\");\n\n   Observable.<Integer>create(subscriber -> {\n        log.info(\"Someone subscribed\");\n        subscriber.onNext(1);\n        subscriber.onNext(2);\n\n        subscriber.onComplete();\n   })\n   .map(val -> {\n         log.info(\"Mapping {}\", val);\n         //what if we do some Thread.sleep here \n         //Thread.sleep(2000);\n         return val * 10;\n   })\n   .subscribe(logNext());\n}\n===============\n11:23:49 [main] INFO BaseTestObservables - Starting\n11:23:50 [main] INFO BaseTestObservables - Someone subscribed\n11:23:50 [main] INFO BaseTestObservables - Mapping 1\n11:23:50 [main] INFO BaseTestObservables - Subscriber received: 10\n11:23:50 [main] INFO BaseTestObservables - Mapping 2\n11:23:50 [main] INFO BaseTestObservables - Subscriber received: 20\n```\nnow let's enable that _Thread.sleep(2000)_ above.\n```\n11:42:12 [main] INFO BaseTestObservables - Starting\n11:42:12 [main] INFO BaseTestObservables - Someone subscribed\n11:42:12 [main] INFO BaseTestObservables - Mapping 1\n11:42:14 [main] INFO BaseTestObservables - Subscriber received: 10\n11:42:14 [main] INFO BaseTestObservables - Mapping 2\n11:42:16 [main] INFO BaseTestObservables - Subscriber received: 20\n``` \nas expected nothing changes, just that we receive the events in the Subscriber delayed by 2 secs.\nTo prevent this, lots of RxJava operators that involve waiting as **delay**,**interval**, **zip** run on a Scheduler, otherwise they would just block the subscribing thread. \nBy default **Schedulers.computation()** is used, but the Scheduler can be passed as a parameter to those methods.\n\nOk so how can we provide different threads to run the different parts of the code.\n\n### subscribeOn\nAs stated above **subscribeOn** allows to specify on which Scheduler thread the subscribtion is made - which thread invokes the code contained in the lambda for Observable.create() -\n(it's **not** abouth the thread for where the code in **.subscribe((val) -> {...})** gets executed). \nSince the operators are lazy and nothing happens until subscription, where the **.subscribeOn()** is called doesn't make any difference.\nAlso calling **.subscribeOn()** multiple times at different positions doesn't have any effect, only the first **.subscribeOn()** Scheduler is considered.   \n\n\n```java\n@Test\npublic void testSubscribeOn() {\n   log.info(\"Starting\");\n\n   Observable<Integer> observable = Observable.create(subscriber -> { \n       //code that will execute inside the IO ThreadPool\n       log.info(\"Starting slow network op\");\n       Helpers.sleepMillis(2000);\n\n       log.info(\"Emitting 1st\");\n       subscriber.onNext(1);\n\n       subscriber.onComplete();\n   });\n\n   observable = observable\n                .subscribeOn(Schedulers.io()) //Specify execution on the IO Scheduler\n                .map(val -> {\n                    int newValue = val * 10;\n                    log.info(\"Mapping {} to {}\", val, newValue);\n                    return newValue;\n                });\n\n   /** Since we are switching the subscription thread we now need to wait \n   * for the Thread to complete so again we are using the CountDownLatch \"trick\" to do it.\n   **/    \n   CountDownLatch latch = new CountDownLatch(1);\n   \n   observable.subscribe(\n                logNext(),\n                logError(latch),\n                logComplete(latch)\n   );\n   \n   Helpers.wait(latch);\n}\n\n===============\n13:16:31 [main] INFO BaseTestObservables - Starting\n13:16:31 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Starting slow network op\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Emitting 1st\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Mapping 1 to 10\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Subscriber received: 10\n13:16:33 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Subscriber got Completed event\n```\nNotice how the code and also the flow down the operators like **.map()** is switched to this new Scheduler that was specified. \n\n\n### observeOn\n**observeOn** allows control to which Scheduler executes the code in the downstream operators.\nSo by using **observeOn()** we changed the Scheduler for the **map** operator, but notice how the last **.observeOn(Schedulers.newThread())** \nwe also influence the code received by the subscriber, while **.subscribeOn()** just had a part on the code executed before we changed with **.observeOn()**  \n\n```java\nlog.info(\"Starting\");\n\nObservable<Integer> observable = \n        Observable.create(subscriber -> { \n                    //code that will execute inside the IO Scheduler\n             log.info(\"Emitting 1st\");\n             subscriber.onNext(1);\n \n             log.info(\"Emitting 2nd\");\n             subscriber.onNext(2);\n \n             subscriber.onComplete();\n        })\n        .subscribeOn(Schedulers.io())\n        .observeOn(Schedulers.computation())\n        .map(val -> {\n              int newValue = val * 10;\n              log.info(\"Mapping {} to {}\", val, newValue);\n              return newValue;\n        })\n        .observeOn(Schedulers.newThread());\n\n   CountDownLatch latch = new CountDownLatch(1);\n   \n   observable.subscribe(\n                logNext(),\n                logError(latch),\n                logComplete(latch)\n   );\n   \n   Helpers.wait(latch);\n\n===============\n19:35:01 [main] INFO BaseTestObservables - Starting\n19:35:01 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Started emitting\n19:35:01 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Emitting 1st\n19:35:01 [RxCachedThreadScheduler-1] INFO BaseTestObservables - Emitting 2nd\n19:35:01 [RxComputationThreadPool-1] INFO BaseTestObservables - Mapping 1 to 10\n19:35:01 [RxNewThreadScheduler-1] INFO BaseTestObservables - Subscriber received: 10\n19:35:01 [RxComputationThreadPool-1] INFO BaseTestObservables - Mapping 2 to 20\n19:35:01 [RxNewThreadScheduler-1] INFO BaseTestObservables - Subscriber received: 20\n19:35:01 [RxNewThreadScheduler-1] INFO BaseTestObservables - Subscriber got Completed event\n```\n\n### back to blocking world \nHow about when we want to switch back to a blocking flow. We saw above how we need to explicitly use latching\nto keep the [main] thread. Say we're incrementally switching from legacy code and we have a Service method\n**Collection\\<String\\> findUsers()** inside this method we can still be reactive but to the caller of the method we\nstill need to block until we get all the elements of the Collection.\nUsing **blockingIterable** will block our Test thread till the Flow completes, waiting\nfor the events to be emitted(we're sleeping just to show it's not completing by chance).\n\n```java\nlog.info(\"Starting\");\n\nFlowable<String> flowable = simpleFlowable()\n                .subscribeOn(Schedulers.io())\n                .subscribeOn(Schedulers.computation())\n                .map(val -> {\n                    String newValue = \"^^\" + val + \"^^\";\n                    log.info(\"Mapping new val {}\", newValue);\n                    Helpers.sleepMillis(500);\n                    return newValue;\n                });\n\nIterable<String> iterable = flowable.blockingIterable(); //this call will block until\n//the stream completes\niterable.forEach(val -> log.info(\"Received {}\", val));\n\n==========================\n17:48:13 [RxCachedThreadScheduler-1] - Started emitting\n17:48:13 [RxCachedThreadScheduler-1] - Emitting 1st\n17:48:13 [RxCachedThreadScheduler-1] - Mapping new val ^^1^^\n17:48:14 [RxCachedThreadScheduler-1] - Emitting 2nd\n17:48:14 [main] - Received ^^1^^\n17:48:14 [RxCachedThreadScheduler-1] - Mapping new val ^^2^^\n17:48:14 [main] - Received ^^2^^\n17:48:14 [main] - Finished blockingIterable\n```\nwe can see the events being received back on the **\\[main\\]** thread.\n\n```java\n    //block until the stream completes or throws an error.\n    flowable.blockingSubscribe(val -> log.info(\"Subscriber received {}\", val));\n```\n\n\n## Flatmap operator\nThe flatMap operator is so important and has so many different uses it deserves it's own category to explain it.\nCode at [Part06FlatMapOperator.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part06FlatMapOperator.java)\n\nI like to think of it as a sort of **fork-join** operation because what flatMap does is it takes individual stream items\nand maps each of them to an Observable(so it creates new Streams from each object) and then 'flattens' the events from \nthese Streams back as coming from a single stream.\n\nWhy this looks like fork-join because for each element you can fork some jobs that keeps emitting results,\nand these results are emitted back as elements to the subscribers downstream\n\n**Rules of thumb** to consider before getting comfortable with flatMap: \n   \n   - When you have an 'item' **T** and a method **T -&lt; Flowable&lt;X&gt;**, you need flatMap. Most common example is when you want \n   to make a remote call that returns an Observable / Flowable . For ex if you have a stream of customerIds, and downstream you\n    want to work with actual Customer objects:    \n   \n   - When you have Observable&lt;Observable&lt;T&gt;&gt;(aka stream of streams) you probably need flatMap. Because flatMap means you are subscribing\n   to each substream.\n\nWe use a simulated remote call that returns asynchronous events. This is a most common scenario to make a remote call for each stream element, \n(although in non reactive world we're more likely familiar with remote operations returning Lists **T -&gt; List&lt;X&gt;**).\nOur simulated remote operation produces as many events as the length of the color string received as parameter every 200ms, \nso for example **red : red0, red1, red2** \n\n```java\nprivate Flowable<String> simulateRemoteOperation(String color) {\n  return Flowable.intervalRange(1, color.length(), 0, 200, TimeUnit.MILLISECONDS)\n             .map(iteration -> color + iteration);\n}\n```\n\nIf we have a stream of color names:\n\n```java\nFlowable<String> colors = Flowable.just(\"orange\", \"red\", \"green\")\n```\n\nto invoke the remote operation: \n\n```java\nFlowable<String> colors = Flowable.just(\"orange\", \"red\", \"green\")\n         .flatMap(colorName -> simulatedRemoteOperation(colorName));\n\ncolors.subscribe(val -> log.info(\"Subscriber received: {}\", val));         \n\n====\n16:44:15 [Thread-0]- Subscriber received: orange0\n16:44:15 [Thread-2]- Subscriber received: green0\n16:44:15 [Thread-1]- Subscriber received: red0\n16:44:15 [Thread-0]- Subscriber received: orange1\n16:44:15 [Thread-2]- Subscriber received: green1\n16:44:15 [Thread-1]- Subscriber received: red1\n16:44:15 [Thread-0]- Subscriber received: orange2\n16:44:15 [Thread-2]- Subscriber received: green2\n16:44:15 [Thread-1]- Subscriber received: red2\n16:44:15 [Thread-0]- Subscriber received: orange3\n16:44:15 [Thread-2]- Subscriber received: green3\n16:44:16 [Thread-0]- Subscriber received: orange4\n16:44:16 [Thread-2]- Subscriber received: green4\n16:44:16 [Thread-0]- Subscriber received: orange5\n```\n\nNotice how the results are coming intertwined(mixed) and it might not be as you expected it.This is because flatMap actually subscribes to it's inner Observables \nreturned from 'simulateRemoteOperation'. You can specify the **concurrency level of flatMap** as a parameter. Meaning \nyou can say how many of the substreams should be subscribed \"concurrently\" - after **onComplete** is triggered on the substreams,\na new substream is subscribed-.\n\nBy setting the concurrency to **1** we don't subscribe to other substreams until the current one finishes:\n\n```\nFlowable<String> colors = Flowable.just(\"orange\", \"red\", \"green\")\n                     .flatMap(val -> simulateRemoteOperation(val), 1); //\n\n```\n\nNotice now there is a sequence from each color before the next one appears\n\n```\n17:15:24 [Thread-0]- Subscriber received: orange0\n17:15:24 [Thread-0]- Subscriber received: orange1\n17:15:25 [Thread-0]- Subscriber received: orange2\n17:15:25 [Thread-0]- Subscriber received: orange3\n17:15:25 [Thread-0]- Subscriber received: orange4\n17:15:25 [Thread-0]- Subscriber received: orange5\n17:15:25 [Thread-1]- Subscriber received: red0\n17:15:26 [Thread-1]- Subscriber received: red1\n17:15:26 [Thread-1]- Subscriber received: red2\n17:15:26 [Thread-2]- Subscriber received: green0\n17:15:26 [Thread-2]- Subscriber received: green1\n17:15:26 [Thread-2]- Subscriber received: green2\n17:15:27 [Thread-2]- Subscriber received: green3\n17:15:27 [Thread-2]- Subscriber received: green4\n```\n\nThere is actually an operator which is basically this **flatMap with 1 concurrency called concatMap**.\n\n\nInside the flatMap we can operate on the substream with the same stream operators\n\n```java\nObservable<Pair<String, Integer>> colorsCounted = colors\n    .flatMap(colorName -> {\n               Observable<Long> timer = Observable.interval(2, TimeUnit.SECONDS);\n\n               return simulateRemoteOperation(colorName) // <- Still a stream\n                              .zipWith(timer, (val, timerVal) -> val)\n                              .count()\n                              .map(counter -> new Pair<>(colorName, counter));\n               }\n    );\n```\n\nWe can also use **switchIfEmpty** to provide some values when the original Publisher doesn't return anything, just completes.\n```java\nFlowable<String> colors = Flowable.just(\"red\", \"\", \"blue\")\n                            .flatMap(colorName -> simulateRemoteOperation(colorName)\n                                                    .switchIfEmpty(Flowable.just(\"NONE\")));\n\n13:11:02  Subscriber received: red0\n13:11:02  Subscriber received: red1\n13:11:02  Subscriber received: red2\n13:11:03  Subscriber received: NONE\n13:11:03  Subscriber received: blue0\n13:11:03  Subscriber received: blue1\n13:11:03  Subscriber received: blue2\n13:11:03  Subscriber received: blue3\n13:11:03  Subscriber got Completed event\n```\n\n**flatMapIterable** is just an easy way to pass each of the elements of a collection\nas a stream\n```\nFlowable<String> colors = Flowable.just(1)\n                .flatMapIterable(it -> generateColors());\n\n\nprivate List<String> generateColors() {\n   return Arrays.asList(\"red\", \"green\", \"blue\");\n}\n\n```\n\n**switchMap** operator also prevents inter-leavings as only one of stream is subscribed at a time, \nbut this is controlled from upstream. If a new value comes from upstream, the current subscribed inner-stream \n gets canceled and a new subscription is made for the new value.\nThe current stream will remain subscribed as long as there are no new values from upstream. \n```java   \nFlowable<String> colors = Flowable.interval(0,400, TimeUnit.MILLISECONDS)\n         .zipWith(Arrays.asList(\"EUR\", \"USD\", \"GBP\"), (it, currency) -> currency)\n         .doOnNext(ev -> log.info(\"Emitting {}\", ev))\n         .switchMap(currency -> simulateRemoteOperation(currency)\n                      .doOnSubscribe((subscription) -> log.info(\"Subscribed new\"))\n                      .doOnCancel(() -> log.info(\"Unsubscribed {}\", currency))\n         );\n```\n\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Emitting EUR\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Subscribed new\n17:45:16 [RxComputationThreadPool-2] INFO BaseTestObservables - Subscriber received: EUR1\n17:45:16 [RxComputationThreadPool-2] INFO BaseTestObservables - Subscriber received: EUR2\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Emitting USD\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Unsubscribed EUR\n17:45:16 [RxComputationThreadPool-1] INFO BaseTestObservables - Subscribed new\n17:45:16 [RxComputationThreadPool-3] INFO BaseTestObservables - Subscriber received: USD1\n17:45:16 [RxComputationThreadPool-3] INFO BaseTestObservables - Subscriber received: USD2\n17:45:17 [RxComputationThreadPool-1] INFO BaseTestObservables - Emitting GBP\n17:45:17 [RxComputationThreadPool-1] INFO BaseTestObservables - Unsubscribed USD\n17:45:17 [RxComputationThreadPool-1] INFO BaseTestObservables - Subscribed new\n17:45:17 [RxComputationThreadPool-3] INFO BaseTestObservables - Subscriber received: USD3\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber received: GBP1\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber received: GBP2\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber received: GBP3\n17:45:17 [RxComputationThreadPool-4] INFO BaseTestObservables - Subscriber got Completed event\n\n## Error handling\nCode at [Part08ErrorHandling.java](https://github.com/balamaci/rxjava-playground/blob/master/src/test/java/com/balamaci/rx/Part08ErrorHandling.java)\n\nExceptions are for exceptional situations.\nThe Reactive Streams specification says that **exceptions are terminal operations**. \nThat means in case an error occurs, it triggers an unsubscription upstream and the error travels downstream to the Subscriber, invoking the 'onError' handler:\n\n```java\nObservable<String> colors = Observable.just(\"green\", \"blue\", \"red\", \"yellow\")\n       .map(color -> {\n              if (\"red\".equals(color)) {\n                        throw new RuntimeException(\"Encountered red\");\n              }\n              return color + \"*\";\n       })\n       .map(val -> val + \"XXX\");\n\ncolors.subscribe(\n         val -> log.info(\"Subscriber received: {}\", val),\n         exception -> log.error(\"Subscriber received error '{}'\", exception.getMessage()),\n         () -> log.info(\"Subscriber completed\")\n);\n```\n\nreturns:\n```\n23:30:17 [main] INFO - Subscriber received: green*XXX\n23:30:17 [main] INFO - Subscriber received: blue*XXX\n23:30:17 [main] ERROR - Subscriber received error 'Encountered red'\n```\nAfter the map() operator encounters an error it unsubscribes(cancels the subscription) from upstream\n(therefore 'yellow' is not even emitted). The error travels downstream and triggers the error handler in the Subscriber.\n\n\nThere are operators to deal with error flow control:\n \n### onErrorReturn\n\nThe 'onErrorReturn' operator replaces an exception with a value:\n\n```java\nFlowable<Integer> numbers = Flowable.just(\"1\", \"3\", \"a\", \"4\", \"5\", \"c\")\n                            .doOnCancel(() -> log.info(\"Subscription canceled\"))\n                            .map(Integer::parseInt) \n                            .onErrorReturn(0);      \nsubscribeWithLog(numbers);\n\n======================\nSubscriber received: 1\nSubscriber received: 3\nSubscription canceled\nSubscriber received: 0\nSubscriber got Completed event\n```\n\nNotice though how **it didn't prevent map() operator from unsubscribing from the Flowable**, but it did \ntrigger the normal **onNext** callback instead of **onError** in the subscriber.\n\n\nLet's introduce a more realcase scenario of a simulated remote request that fails whenever it's invoked\nwith \"red\" and \"black\" color parameters otherwise just add some \\*s.\n\n\n```java\nprivate Observable<String> simulateRemoteOperation(String color) {\n    return Observable.<String>create(subscriber -> {\n         if (\"red\".equals(color)) {\n              log.info(\"Emitting RuntimeException for {}\", color);\n              throw new RuntimeException(\"Color red raises exception\");\n         }\n         if (\"black\".equals(color)) {\n              log.info(\"Emitting IllegalArgumentException for {}\", color);\n              throw new IllegalArgumentException(\"Black is not a color\");\n         }\n\n         String value = \"**\" + color + \"**\";\n\n         log.info(\"Emitting {}\", value);\n         subscriber.onNext(value);\n         subscriber.onCompleted();\n    });\n}\n\nFlowable<String> colors = Flowable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n                .flatMap(color -> simulateRemoteOperation(color))\n                .onErrorReturn(throwable -> \"-blank-\");\n                \nsubscribeWithLog(colors);\n\n============\n\n22:15:51 [main] INFO - Emitting **green**\n22:15:51 [main] INFO - Subscriber received: **green**\n22:15:51 [main] INFO - Emitting **blue**\n22:15:51 [main] INFO - Subscriber received: **blue**\n22:15:51 [main] INFO - Emitting RuntimeException for red\n22:15:51 [main] INFO - Subscriber received: -blank-\n22:15:51 [main] INFO - Subscriber got Completed event\n```\nflatMap encounters an error when it subscribes to 'red' substreams and thus still unsubscribe from 'colors' \nstream and the remaining colors are not longer emitted\n\n\n```java\nFlowable<String> colors = Flowable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n                .flatMap(color -> simulateRemoteOperation(color)\n                                    .onErrorReturn(throwable -> \"-blank-\")\n                );\n```\nonErrorReturn() is applied to the flatMap substream and thus translates the exception to a value and so flatMap \ncontinues on with the other colors after red\n\nreturns:\n```\n22:15:51 [main] INFO - Emitting **green**\n22:15:51 [main] INFO - Subscriber received: **green**\n22:15:51 [main] INFO - Emitting **blue**\n22:15:51 [main] INFO - Subscriber received: **blue**\n22:15:51 [main] INFO - Emitting RuntimeException for red\n22:15:51 [main] INFO - Subscriber received: -blank-\n22:15:51 [main] INFO - Emitting **white**\n22:15:51 [main] INFO - Subscriber received: **white**\n22:15:51 [main] INFO - Emitting **blue**\n22:15:51 [main] INFO - Subscriber received: **blue**\n22:15:51 [main] INFO - Subscriber got Completed event\n```\n\n### onErrorResumeNext\nonErrorResumeNext() returns a stream instead of an exception, useful for example to invoke a fallback \nmethod that returns an alternate Stream\n\n```java\nObservable<String> colors = Observable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n     .flatMap(color -> simulateRemoteOperation(color)\n                        .onErrorResumeNext(th -> {\n                            if (th instanceof IllegalArgumentException) {\n                                return Observable.error(new RuntimeException(\"Fatal, wrong arguments\"));\n                            }\n                            return fallbackRemoteOperation();\n                        })\n     );\n\nprivate Observable<String> fallbackRemoteOperation() {\n        return Observable.just(\"blank\");\n}\n```\n\n\n\n## Retrying\n\n### timeout()\nTimeout operator raises exception when there are no events incoming before it's predecessor in the specified time limit.\n\n### retry()\n**retry()** - resubscribes in case of exception to the Observable\n\n```java\nFlowable<String> colors = Flowable.just(\"red\", \"blue\", \"green\", \"yellow\")\n       .concatMap(color -> delayedByLengthEmitter(TimeUnit.SECONDS, color) \n                             //if there are no events flowing in the timeframe   \n                             .timeout(6, TimeUnit.SECONDS)  \n                             .retry(2)\n                             .onErrorResumeNext(Observable.just(\"blank\"))\n       );\n\nsubscribeWithLog(colors.toBlocking());\n```\n\nreturns\n```\n12:40:16 [main] INFO - Received red delaying for 3 \n12:40:19 [main] INFO - Subscriber received: red\n12:40:19 [RxComputationScheduler-2] INFO - Received blue delaying for 4 \n12:40:23 [main] INFO - Subscriber received: blue\n12:40:23 [RxComputationScheduler-4] INFO - Received green delaying for 5 \n12:40:28 [main] INFO - Subscriber received: green\n12:40:28 [RxComputationScheduler-6] INFO - Received yellow delaying for 6 \n12:40:34 [RxComputationScheduler-7] INFO - Received yellow delaying for 6 \n12:40:40 [RxComputationScheduler-1] INFO - Received yellow delaying for 6 \n12:40:46 [main] INFO - Subscriber received: blank\n12:40:46 [main] INFO - Subscriber got Completed event\n```\n\nWhen you want to retry considering the thrown exception type:\n\n```java\nObservable<String> colors = Observable.just(\"blue\", \"red\", \"black\", \"yellow\")\n         .flatMap(colorName -> simulateRemoteOperation(colorName)\n                .retry((retryAttempt, exception) -> {\n                           if (exception instanceof IllegalArgumentException) {\n                               log.error(\"{} encountered non retry exception \", colorName);\n                               return false;\n                           }\n                           log.info(\"Retry attempt {} for {}\", retryAttempt, colorName);\n                           return retryAttempt <= 2;\n                })\n                .onErrorResumeNext(Observable.just(\"generic color\"))\n         );\n```\n\n```\n13:21:37 [main] INFO - Emitting **blue**\n13:21:37 [main] INFO - Emitting RuntimeException for red\n13:21:37 [main] INFO - Retry attempt 1 for red\n13:21:37 [main] INFO - Emitting RuntimeException for red\n13:21:37 [main] INFO - Retry attempt 2 for red\n13:21:37 [main] INFO - Emitting RuntimeException for red\n13:21:37 [main] INFO - Retry attempt 3 for red\n13:21:37 [main] INFO - Emitting IllegalArgumentException for black\n13:21:37 [main] ERROR - black encountered non retry exception \n13:21:37 [main] INFO - Emitting **yellow**\n13:21:37 [main] INFO - Subscriber received: **blue**\n13:21:37 [main] INFO - Subscriber received: generic color\n13:21:37 [main] INFO - Subscriber received: generic color\n13:21:37 [main] INFO - Subscriber received: **yellow**\n13:21:37 [main] INFO - Subscriber got Completed event\n```\n\n### retryWhen\nA more complex retry logic like implementing a backoff strategy in case of exception\nThis can be obtained with **retryWhen**(exceptionObservable -> Observable)\n\nretryWhen resubscribes when an event from an Observable is emitted. It receives as parameter an exception stream\n     \nwe zip the exceptionsStream with a .range() stream to obtain the number of retries,\nhowever we want to wait a little before retrying so in the zip function we return a delayed event - .timer()\n\nThe delay also needs to be subscribed to be effected so we also flatMap\n\n```java\nObservable<String> colors = Observable.just(\"blue\", \"green\", \"red\", \"black\", \"yellow\");\n\ncolors.flatMap(colorName -> \n                   simulateRemoteOperation(colorName)\n                      .retryWhen(exceptionStream -> exceptionStream\n                                    .zipWith(Observable.range(1, 3), (exc, attempts) -> {\n                                        //don't retry for IllegalArgumentException\n                                        if(exc instanceof IllegalArgumentException) {\n                                             return Observable.error(exc);\n                                        }\n\n                                        if(attempts < 3) {\n                                             return Observable.timer(2 * attempts, TimeUnit.SECONDS);\n                                        }\n                                        return Observable.error(exc);\n                                    })\n                                    .flatMap(val -> val)\n                      )\n                      .onErrorResumeNext(Observable.just(\"generic color\")\n                   )\n            );\n```\n\n```\n15:20:23 [main] INFO - Emitting **blue**\n15:20:23 [main] INFO - Emitting **green**\n15:20:23 [main] INFO - Emitting RuntimeException for red\n15:20:23 [main] INFO - Emitting IllegalArgumentException for black\n15:20:23 [main] INFO - Emitting **yellow**\n15:20:23 [main] INFO - Subscriber received: **blue**\n15:20:23 [main] INFO - Subscriber received: **green**\n15:20:23 [main] INFO - Subscriber received: generic color\n15:20:23 [main] INFO - Subscriber received: **yellow**\n15:20:25 [RxComputationScheduler-1] INFO - Emitting RuntimeException for red\n15:20:29 [RxComputationScheduler-2] INFO - Emitting RuntimeException for red\n15:20:29 [main] INFO - Subscriber received: generic color\n15:20:29 [main] INFO - Subscriber got Completed event\n```\n\n**retryWhen vs repeatWhen** \nWith similar names it worth noting the difference.\n \n   - repeat() resubscribes when it receives onCompleted().\n   - retry() resubscribes when it receives onError().\n   \nExample using repeatWhen() to implement periodic polling\n```java\nremoteOperation.repeatWhen(completed -> completed\n                                     .delay(2, TimeUnit.SECONDS))                                                       \n```\n   \n## Backpressure\n\nIt can be the case of a slow consumer that cannot keep up with the producer that is producing too many events\nthat the subscriber cannot process. \n\nBackpressure relates to a feedback mechanism through which the subscriber can signal to the producer how much data \nit can consume and so to produce only that amount.\n\nThe [reactive-streams](https://github.com/reactive-streams/reactive-streams-jvm) section above we saw that besides the \n**onNext, onError** and **onComplete** handlers, the Subscriber\nhas an **onSubscribe(Subscription)**, Subscription through which it can signal upstream it's ready to receive a number \nof items and after it processes the items request another batch.\n\n\n```java\npublic interface Subscriber<T> {\n    //signals to the Publisher to start sending events\n    public void onSubscribe(Subscription s);     \n    \n    public void onNext(T t);\n    public void onError(Throwable t);\n    public void onComplete();\n}\n```\n\nThe methods exposed by **Subscription** through which the subscriber comunicates with the upstream:\n\n```java\npublic interface Subscription {\n    public void request(long n); //request n items\n    public void cancel();\n}\n```\n\nSo in theory the Subscriber can prevent being overloaded by requesting an initial number of items. The Publisher would\nsend those items downstream and not produce any more, until the Subscriber would request more. We say in theory because\nuntil now we did not see a custom **onSubscribe(Subscription)** request being implemented. This is because if not specified explicitly,\nthere is a default implementation which requests of **Long.MAX_VALUE** which basically means \"send all you have\".\n\nNeither did we see the code in the producer that takes consideration of the number of items requested by the subscriber. \n\n```java\nFlowable.create(subscriber -> {\n      log.info(\"Started emitting\");\n\n      for(int i=0; i < 300; i++) {\n           if(subscriber.isCanceled()) {\n              return;\n           }\n           log.info(\"Emitting {}\", i);\n           subscriber.next(i);\n      }\n\n      subscriber.complete();\n}, BackpressureStrategy.BUFFER); //BackpressureStrategy will be explained further bellow\n```\nLooks like it's not possible to slow down production based on request(as there is no reference to the requested items),\nwe can at most stop production if the subscriber canceled subscription. \n\nThis can be done if we extend Flowable so we can pass our custom Subscription type to the downstream subscriber:\n\n```java\nprivate class CustomRangeFlowable extends Flowable<Integer> {\n\n        private int startFrom;\n        private int count;\n\n        CustomRangeFlowable(int startFrom, int count) {\n            this.startFrom = startFrom;\n            this.count = count;\n        }\n\n        @Override\n        public void subscribeActual(Subscriber<? super Integer> subscriber) {\n            subscriber.onSubscribe(new CustomRangeSubscription(startFrom, count, subscriber));\n        }\n\n        class CustomRangeSubscription implements Subscription {\n\n            volatile boolean cancelled;\n            boolean completed = false;\n            \n            private int count;\n            private int currentCount;\n            private int startFrom;\n\n            private Subscriber<? super Integer> actualSubscriber;\n\n            CustomRangeSubscription(int startFrom, int count, Subscriber<? super Integer> actualSubscriber) {\n                this.count = count;\n                this.startFrom = startFrom;\n                this.actualSubscriber = actualSubscriber;\n            }\n\n            @Override\n            public void request(long items) {\n                log.info(\"Downstream requests {} items\", items);\n                for(int i=0; i < items; i++) {\n                    if(cancelled || completed) {\n                        return;\n                    }\n\n                    if(currentCount == count) {\n                        completed = true;\n                        if(cancelled) {\n                            return;\n                        }\n\n                        actualSubscriber.onComplete();\n                        return;\n                    }\n\n                    int emitVal = startFrom + currentCount;\n                    currentCount++;\n                    actualSubscriber.onNext(emitVal);\n                }\n            }\n\n            @Override\n            public void cancel() {\n                cancelled = true;\n            }\n        }\n    }\n```   \nNow lets see how we can custom control how many items we request from upstream, to simulate an initial big request, \nand then a request for other smaller batches of items as soon as the subscriber finishes and is ready for another batch.\n  \n```java\nFlowable<Integer> flowable = new CustomRangeFlowable(5, 10);\n\nflowable.subscribe(new Subscriber<Integer>() {\n\n       private Subscription subscription;\n       private int backlogItems;\n\n       private final int BATCH = 2;\n       private final int INITIAL_REQ = 5;\n\n       @Override\n       public void onSubscribe(Subscription subscription) {\n                this.subscription = subscription;\n                backlogItems = INITIAL_REQ;\n\n                log.info(\"Initial request {}\", backlogItems);\n                subscription.request(backlogItems);\n            }\n\n            @Override\n            public void onNext(Integer val) {\n                log.info(\"Subscriber received {}\", val);\n                backlogItems --;\n\n                if(backlogItems == 0) {\n                    backlogItems = BATCH;\n                    subscription.request(BATCH);\n                }\n            }\n\n            @Override\n            public void onError(Throwable throwable) {\n                log.info(\"Subscriber encountered error\");\n            }\n\n            @Override\n            public void onComplete() {\n                log.info(\"Subscriber completed\");\n            }\n        });\n=====================\nInitial request 5\nDownstream requests 5 items\nSubscriber received 5\nSubscriber received 6\nSubscriber received 7\nSubscriber received 8\nSubscriber received 9\nDownstream requests 2 items\nSubscriber received 10\nSubscriber received 11\nDownstream requests 2 items\nSubscriber received 12\nSubscriber received 13\nDownstream requests 2 items\nSubscriber received 14\nSubscriber completed        \n```  \n\nReturning to the _Flowable.create()_ example since it's not taking any account of the requested \nitems by the subscriber, does it mean it might overwhelm a slow Subscriber? \n\n```java\nprivate Flowable<Integer> createFlowable(int items,\n                     BackpressureStrategy backpressureStrategy) {\n\nreturn Flowable.create(subscriber -> {\n        log.info(\"Started emitting\");\n\n        for (int i = 0; i < items; i++) {\n            if(subscriber.isCancelled()) {\n                 return;\n            }\n                \n            log.info(\"Emitting {}\", i);\n            subscriber.onNext(i);\n        }\n\n        subscriber.onComplete();\n}, backpressureStrategy); //can be BackpressureStrategy.DROP, BUFFER, LATEST,..\n```\nThis is where the 2nd parameter _BackpressureStrategy_ comes in that allows you to specify what to do \nin the case.\n \n   - BackpressureStrategy.BUFFER buffer in memory the events that overflow. Of course is we don't drop over some threshold, it might lead to OufOfMemory. \n   - BackpressureStrategy.DROP just drop the overflowing events\n   - BackpressureStrategy.LATEST keep only recent event and discards previous unconsumed events.\n   - BackpressureStrategy.ERROR we get an error in the subscriber immediately  \n   - BackpressureStrategy.MISSING means we don't care about backpressure(we let one of the downstream operators\n   onBackpressureXXX handle it -explained further down-)\n\n  \nStill what does it mean to 'overwhelm' the subscriber? \nIt means to emit more items than requested by downstream subscriber.\nBut we said that by default the subscriber requests Long.MAX_VALUE since the code \n**flowable.subscribe(onNext(), onError, onComplete)** uses a default **onSubscribe**:\n```\n(subscription) -> subscription.request(Long.MAX_VALUE);\n```\n\nso unless we override it like in our custom Subscriber above, it means it would never overflow. But between the Publisher and the Subscriber you'd have a series of operators. \nWhen we subscribe, a Subscriber travels up through all operators to the original Publisher and some operators override \nthe requested items upstream. One such operator is **observeOn**() which makes it's own request to the upstream Publisher(256 by default),\nbut can take a parameter to specify the request size.\n\n```\nFlowable<Integer> flowable = createFlowable(5, BackpressureStrategy.DROP)\n                .observeOn(Schedulers.io(), false, 3);\nflowable.subscribe((val) -> {\n                               log.info(\"Subscriber received: {}\", val);\n                               Helpers.sleepMillis(millis);\n                           }, logError(), logComplete());\n======\n[main] - Started emitting\n[main] - Emitting 0\n[main] - Emitting 1\n[main] - Emitting 2\n[main] - Emitting 3\n[main] - Emitting 4\n[RxCachedThreadScheduler-1] - Subscriber received: 0\n[RxCachedThreadScheduler-1] - Subscriber received: 1\n[RxCachedThreadScheduler-1] - Subscriber received: 2\n[RxCachedThreadScheduler-1] - Subscriber got Completed event  \n```\nThis is expected, as the subscription travels upstream through the operators to the source Flowable, while initially\nthe Subscriber requesting Long.MAX_VALUE from the upstream operator **observeOn**, which in turn subscribes to the source and it requests just 3 items from the source instead.\nSince we used **BackpressureStrategy.DROP** all the items emitted outside the expected 3, get discarded and thus never reach our subscriber.\n\nYou may wonder what would have happened if we didn't use **observeOn**. We had to use it if we wanted to be able\nto produce faster than the subscriber(it wasn't just to show a limited request operator), because we'd need a \nseparate thread to produce events faster than the subscriber processes them.   \n\nAlso you can transform an Observable to Flowable by specifying a BackpressureStrategy, otherwise Observables \njust throw exception on overflowing(same as using BackpressureStrategy.DROP in Flowable.create()).\n```\nFlowable flowable = observable.toFlowable(BackpressureStrategy.DROP)\n```\nso can a hot Publisher be converted to a Flowable:\n```\nPublishSubject<Integer> subject = PublishSubject.create();\n\nFlowable<Integer> flowable = subject\n                .toFlowable(BackpressureStrategy.DROP)\n```\n\nThere are also specialized operators to handle backpressure the onBackpressureXXX operators: **onBackpressureBuffer**,\n**onBackpressureDrop**, **onBackpressureLatest**\n\nThese operators request Long.MAX_VALUE(unbounded amount) from upstream and then take it upon themselves to manage the \nrequests from downstream. \nIn the case of _onBackpressureBuffer_ it adds in an internal queue and send downstream the events as requested,\n_onBackpressureDrop_ just discards events that are received from upstream more than requested from downstream, \n_onBackpressureLatest_ also drops emitted events excluding the last emitted event(most recent).  \n\n```java\nFlowable<Integer> flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureBuffer(5, () -> log.info(\"Buffer has overflown\"));\n\nflowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\nsubscribeWithSlowSubscriber(flowable);                \n\n=====                \n[main] - Started emitting\n[main] - Emitting 0\n[main] - Emitting 1\n[RxCachedThreadScheduler-1] - Subscriber received: 0\n[main] - Emitting 2\n[main] - Emitting 3\n[main] - Emitting 4\n[main] - Emitting 5\n[main] - Emitting 6\n[main] - Emitting 7\n[main] - Emitting 8\n[main] - Emitting 9\n[main] - Buffer has overflown\n[RxCachedThreadScheduler-1] ERROR - Subscriber received error 'Buffer is full'                \n```\n\nWe create the Flowable with _BackpressureStrategy.MISSING_ saying we don't care about backpressure\nbut let one of the onBackpressureXXX operators handle it.\nNotice however \n\n\n\nChaining together multiple onBackpressureXXX operators doesn't actually make sense\nUsing something like\n\n```java\nFlowable<Integer> flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                 .onBackpressureBuffer(5)\n                 .onBackpressureDrop((val) -> log.info(\"Dropping {}\", val))\nflowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n                 \nsubscribeWithSlowSubscriber(flowable);\n```\n\nis not behaving as probably you'd expected - buffer 5 values, and then dropping overflowing events-.\nBecause _onBackpressureDrop_ subscribes to the previous _onBackpressureBuffer_ operator\nsignaling it's requesting **Long.MAX_VALUE**(unbounded amount) from it. \nThus **onBackpressureBuffer** will never feel its subscriber is overwhelmed and never \"trigger\", meaning that the last \nonBackpressureXXX operator overrides the previous one if they are chained.\n\nOf course for implementing an event dropping strategy after a full buffer, there is the special overrided\nversion of **onBackpressureBuffer** that takes a **BackpressureOverflowStrategy**.\n\n```java\nFlowable<Integer> flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureBuffer(5, () -> log.info(\"Buffer has overflown\"),\n                                            BackpressureOverflowStrategy.DROP_OLDEST);\n\nflowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n\nsubscribeWithSlowSubscriber(flowable);\n\n===============\n[main] - Started emitting\n[main] - Emitting 0\n[main] - Emitting 1\n[RxCachedThreadScheduler-1] - Subscriber received: 0\n[main] - Emitting 2\n[main] - Emitting 3\n[main] - Emitting 4\n[main] - Emitting 5\n[main] - Emitting 6\n[main] - Emitting 7\n[main] - Emitting 8\n[main] - Buffer has overflown\n[main] - Emitting 9\n[main] - Buffer has overflown\n[RxCachedThreadScheduler-1] - Subscriber received: 1\n[RxCachedThreadScheduler-1] - Subscriber received: 2\n[RxCachedThreadScheduler-1] - Subscriber received: 5\n[RxCachedThreadScheduler-1] - Subscriber received: 6\n[RxCachedThreadScheduler-1] - Subscriber received: 7\n[RxCachedThreadScheduler-1] - Subscriber received: 8\n[RxCachedThreadScheduler-1] - Subscriber received: 9\n[RxCachedThreadScheduler-1] - Subscriber got Completed event\n```\n\nonBackpressureXXX operators can be added whenever necessary and it's not limited to cold publishers and we can use them \non hot publishers also.\n\n## Articles and books for further reading\n[Reactive Programming with RxJava](http://shop.oreilly.com/product/0636920042228.do)\n\n  \n"
  },
  {
    "path": "_config.yml",
    "content": "theme: jekyll-theme-cayman"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.balamaci</groupId>\n    <artifactId>rxjava-playground</artifactId>\n    <version>1.0-SNAPSHOT</version>\n    <name>RxJava Playground</name>\n    <description>RxJava Playground - Test scenarios describing RxJava functionality</description>\n\n    <properties>\n        <rxjava.version>2.2.3</rxjava.version>\n        <slf4j.version>1.7.25</slf4j.version>\n    </properties>\n\n    <dependencies>\n\n        <dependency>\n            <groupId>io.reactivex.rxjava2</groupId>\n            <artifactId>rxjava</artifactId>\n            <version>${rxjava.version}</version>\n        </dependency>\n\n        <!-- Logging -->\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n            <version>${slf4j.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-simple</artifactId>\n            <version>${slf4j.version}</version>\n        </dependency>\n\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <version>4.12</version>\n            <scope>test</scope>\n        </dependency>\n\n        <!-- https://mvnrepository.com/artifact/io.vavr/vavr -->\n        <dependency>\n            <groupId>io.vavr</groupId>\n            <artifactId>vavr</artifactId>\n            <version>0.9.2</version>\n        </dependency>\n\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <inherited>true</inherited>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <version>3.1</version>\n                <configuration>\n                    <source>1.8</source>\n                    <target>1.8</target>\n                    <encoding>UTF-8</encoding>\n                    <showWarnings>true</showWarnings>\n                    <showDeprecation>true</showDeprecation>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/BaseTestObservables.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Helpers;\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.reactivex.Single;\nimport io.reactivex.functions.Action;\nimport io.reactivex.functions.Consumer;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author sbalamaci\n */\npublic interface BaseTestObservables {\n\n    Logger log = LoggerFactory.getLogger(BaseTestObservables.class);\n\n    default Flowable<Integer> simpleFlowable() {\n        return Flowable.create(subscriber -> {\n            log.info(\"Started emitting\");\n\n            log.info(\"Emitting 1st\");\n            subscriber.onNext(1);\n\n            log.info(\"Emitting 2nd\");\n            subscriber.onNext(2);\n\n            subscriber.onComplete();\n        }, BackpressureStrategy.BUFFER);\n    }\n\n    default <T> void subscribeWithLog(Flowable<T> flowable) {\n        flowable.subscribe(\n                logNext(),\n                logError(),\n                logComplete()\n        );\n    }\n\n    default <T> void subscribeWithLog(Observable<T> observable) {\n        observable.subscribe(\n                logNext(),\n                logError(),\n                logComplete()\n        );\n    }\n\n    default <T> void subscribeWithLogOutputWaitingForComplete(Observable<T> observable) {\n        CountDownLatch latch = new CountDownLatch(1);\n\n        observable.subscribe(\n                logNext(),\n                logError(latch),\n                logComplete(latch)\n        );\n\n        Helpers.wait(latch);\n    }\n\n    default <T> void subscribeWithLog(Single<T> single) {\n        single.subscribe(\n                val -> log.info(\"Subscriber received: {}\", val),\n                logError()\n        );\n    }\n\n    default <T> void subscribeWithLogOutputWaitingForComplete(Flowable<T> flowable) {\n        CountDownLatch latch = new CountDownLatch(1);\n\n        flowable.subscribe(\n                logNext(),\n                logError(latch),\n                logComplete(latch)\n        );\n\n        Helpers.wait(latch);\n    }\n\n    default <T> void subscribeWithLogOutputWaitingForComplete(Single<T> single) {\n        CountDownLatch latch = new CountDownLatch(1);\n\n        single.subscribe(\n                val -> {\n                    log.info(\"Subscriber received: {} and completed\", val);\n                    latch.countDown();\n                },\n                logError(latch)\n        );\n\n        Helpers.wait(latch);\n    }\n\n    default  <T> Flowable<T> periodicEmitter(T t1, T t2, T t3, int interval, TimeUnit unit) {\n        return periodicEmitter(t1, t2, t3, interval, unit, interval);\n    }\n\n    default  <T> Flowable<T> periodicEmitter(T t1, T t2, T t3, int interval,\n                                               TimeUnit unit, int initialDelay) {\n        Flowable<T> itemsStream = Flowable.just(t1, t2, t3);\n        Flowable<Long> timer = Flowable.interval(initialDelay, interval, unit);\n\n        return Flowable.zip(itemsStream, timer, (key, val) -> key);\n    }\n\n    default  <T> Observable<T> periodicEmitter(T[] items, int interval,\n                                               TimeUnit unit, int initialDelay) {\n        Observable<T> itemsStream = Observable.fromArray(items);\n        Observable<Long> timer = Observable.interval(initialDelay, interval, unit);\n\n        return Observable.zip(itemsStream, timer, (key, val) -> key);\n    }\n\n    default  <T> Observable<T> periodicEmitter(T[] items, int interval,\n                                               TimeUnit unit) {\n        return periodicEmitter(items, interval, unit);\n    }\n\n    default  Flowable<String> delayedByLengthEmitter(TimeUnit unit, String...items) {\n        Flowable<String> itemsStream = Flowable.fromArray(items);\n\n        return itemsStream.concatMap(item -> Flowable.just(item)\n                        .doOnNext(val -> log.info(\"Received {} delaying for {} \", val, val.length()))\n                        .delay(item.length(), unit)\n                );\n    }\n\n    default <T> Consumer<? super T> logNext() {\n        return (Consumer<T>) val -> log.info(\"Subscriber received: {}\", val);\n    }\n\n    default <T> Consumer<? super T> logNextAndSlowByMillis(int millis) {\n        return (Consumer<T>) val -> {\n            log.info(\"Subscriber received: {}\", val);\n            Helpers.sleepMillis(millis);\n        };\n    }\n\n    default Consumer<? super Throwable> logError() {\n        return err -> log.error(\"Subscriber received error '{}'\", err.getMessage());\n    }\n\n    default Consumer<? super Throwable> logError(CountDownLatch latch) {\n        return err -> {\n            log.error(\"Subscriber received error '{}'\", err.getMessage());\n            latch.countDown();\n        };\n    }\n\n    default Action logComplete() {\n        return () -> log.info(\"Subscriber got Completed event\");\n    }\n\n    default Action logComplete(CountDownLatch latch) {\n        return () -> {\n            log.info(\"Subscriber got Completed event\");\n            latch.countDown();\n        };\n    }\n\n}\n\n\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part01CreateFlowable.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Helpers;\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.reactivex.Single;\nimport io.reactivex.disposables.Disposable;\nimport org.junit.Test;\n\nimport java.util.Arrays;\nimport java.util.concurrent.CompletableFuture;\n\n/**\n *\n *\n * @author sbalamaci\n */\npublic class Part01CreateFlowable implements BaseTestObservables {\n\n\n    @Test\n    public void just() {\n        Flowable<Integer> flowable = Flowable.just(1, 5, 10);\n\n        flowable.subscribe(\n                val -> log.info(\"Subscriber received: {}\", val));\n    }\n\n    @Test\n    public void range() {\n        Flowable<Integer> flowable = Flowable.range(1, 10);\n\n        flowable.subscribe(\n                val -> log.info(\"Subscriber received: {}\", val));\n    }\n\n    @Test\n    public void fromArray() {\n        Flowable<String> flowable = Flowable.fromArray(new String[]{\"red\", \"green\", \"blue\", \"black\"});\n\n        flowable.subscribe(\n                val -> log.info(\"Subscriber received: {}\"));\n    }\n\n    @Test\n    public void fromIterable() {\n        Flowable<String> flowable = Flowable.fromIterable(Arrays.asList(\"red\", \"green\", \"blue\"));\n\n        flowable.subscribe(\n                val -> log.info(\"Subscriber received: {}\"));\n    }\n\n    /**\n     * We can also create a stream from Future, making easier to switch from legacy code to reactive\n     */\n    @Test\n    public void fromFuture() {\n        CompletableFuture<String> completableFuture = CompletableFuture.\n                supplyAsync(() -> { //starts a background thread the ForkJoin common pool\n                      Helpers.sleepMillis(100);\n                      return \"red\";\n                });\n\n        Single<String> single = Single.fromFuture(completableFuture);\n        single.subscribe(val -> log.info(\"Stream completed successfully : {}\", val));\n    }\n\n\n\n    /**\n     * Using Flowable.create to handle the actual emissions of events with the events like onNext, onComplete, onError\n     * <p>\n     * When subscribing to the Flowable / Observable with flowable.subscribe(), the lambda code inside create() gets executed.\n     * Flowable.subscribe can take 3 handlers for each type of event - onNext, onError and onComplete\n     * <p>\n     * When using Observable.create you need to be aware of <b>Backpressure</b> and that Observables based on 'create' method\n     * are not Backpressure aware {@see Part09BackpressureHandling}.\n     */\n    @Test\n    public void createSimpleObservable() {\n        Flowable<Integer> flowable = Flowable.create(subscriber -> {\n            log.info(\"Started emitting\");\n\n            log.info(\"Emitting 1st\");\n            subscriber.onNext(1);\n\n            log.info(\"Emitting 2nd\");\n            subscriber.onNext(2);\n\n            subscriber.onComplete();\n        }, BackpressureStrategy.BUFFER);\n\n        log.info(\"Subscribing\");\n        Disposable subscription = flowable.subscribe(\n                val -> log.info(\"Subscriber received: {}\", val),\n                err -> log.error(\"Subscriber received error\", err),\n                () -> log.info(\"Subscriber got Completed event\"));\n    }\n\n\n    /**\n     * Observable emits an Error event which is a terminal operation and the subscriber is no longer executing\n     * it's onNext callback. We're actually breaking the the Observable contract that we're still emitting events\n     * after onComplete or onError have fired.\n     */\n    @Test\n    public void createSimpleObservableThatEmitsError() {\n        Observable<Integer> observable = Observable.create(subscriber -> {\n            log.info(\"Started emitting\");\n\n            log.info(\"Emitting 1st\");\n            subscriber.onNext(1);\n\n            subscriber.onError(new RuntimeException(\"Test exception\"));\n\n            log.info(\"Emitting 2nd\");\n            subscriber.onNext(2);\n        });\n\n        Disposable disposable = observable.subscribe(\n                val -> log.info(\"Subscriber received: {}\", val),\n                err -> log.error(\"Subscriber received error\", err),\n                () -> log.info(\"Subscriber got Completed event\")\n        );\n    }\n\n    /**\n     * Observables are lazy, meaning that the code inside create() doesn't get executed without subscribing to the Observable\n     * So even if we sleep for a long time inside create() method(to simulate a costly operation),\n     * without subscribing to this Observable the code is not executed and the method returns immediately.\n     */\n    @Test\n    public void flowablesAreLazy() {\n        Observable<Integer> flowable = Observable.create(subscriber -> {\n            log.info(\"Started emitting but sleeping for 5 secs\"); //this is not executed\n            Helpers.sleepMillis(5000);\n            subscriber.onNext(1);\n        });\n        log.info(\"Finished\");\n    }\n\n    /**\n     * When subscribing to an Observable, the create() method gets executed for each subscription\n     * this means that the events inside create are re-emitted to each subscriber. So every subscriber will get the\n     * same events and will not lose any events.\n     */\n    @Test\n    public void multipleSubscriptionsToSameObservable() {\n        Observable<Integer> flowable = Observable.create(subscriber -> {\n            log.info(\"Started emitting\");\n\n            log.info(\"Emitting 1st event\");\n            subscriber.onNext(1);\n\n            log.info(\"Emitting 2nd event\");\n            subscriber.onNext(2);\n\n            subscriber.onComplete();\n        });\n\n        log.info(\"Subscribing 1st subscriber\");\n        flowable.subscribe(val -> log.info(\"First Subscriber received: {}\", val));\n\n        log.info(\"=======================\");\n\n        log.info(\"Subscribing 2nd subscriber\");\n        flowable.subscribe(val -> log.info(\"Second Subscriber received: {}\", val));\n    }\n\n    /**\n     * Inside the create() method, we can check is there are still active subscribers to our Observable.\n     * It's a way to prevent to do extra work(like for ex. querying a datasource for entries) if no one is listening\n     * In the following example we'd expect to have an infinite stream, but because we stop if there are no active\n     * subscribers we stop producing events.\n     * The take() operator unsubscribes from the Observable after it's received the specified amount of events\n     * while in the same time calling onComplete() downstream.\n     */\n    @Test\n    public void showUnsubscribeObservable() {\n        Observable<Integer> observable = Observable.create(subscriber -> {\n            int i = 1;\n            while(true) {\n                if(subscriber.isDisposed()) {\n                    break;\n                }\n\n                subscriber.onNext(i++);\n            }\n            //subscriber.onCompleted(); too late to emit Complete event since subscriber already unsubscribed\n\n            subscriber.setCancellable(() -> log.info(\"Subscription canceled\"));\n        });\n\n        observable\n                .take(5)\n                .map(val -> \"*\" + val + \"*\")\n                .subscribe(\n                        val -> log.info(\"Subscriber received: {}\", val),\n                        err -> log.error(\"Subscriber received error\", err),\n                        () -> log.info(\"Subscriber got Completed event\") //The Complete event is triggered by 'take()' operator\n        );\n    }\n\n\n    /**\n     * .defer acts as a factory of Flowables, just when subscribed it actually invokes the logic to create the\n     * Flowable to be emitted.\n     * It's an easy way to switch from a blocking method to a reactive Single/Flowable.\n     * Simply using Flowable.just(blockingOp()) would still block, as Java needs to resolve the parameter when invoking\n     * Flux.just(param) method, so blockingOp() method would still be invoked(and block).\n     *\n     * The solution is to wrap the blockingOp() method inside a lambda that gets passed to .defer(() -> blockingOp())\n     *\n     */\n    @Test\n    public void deferCreateObservable() {\n        log.info(\"Starting blocking Flowable\");\n        Flowable<String> flowableBlocked = Flowable.just((blockingOperation()));\n        log.info(\"After blocking Flowable\");\n\n        log.info(\"Starting defered op\");\n        Flowable<String> stream = Flowable.defer(() -> Flowable.just(blockingOperation()));\n        log.info(\"After defered op\");\n\n        log.info(\"Sleeping a little before subscribing and executing the defered code\");\n        Helpers.sleepMillis(2000);\n\n        log.info(\"Subscribing\");\n        subscribeWithLogOutputWaitingForComplete(stream);\n    }\n\n    private String blockingOperation() {\n        log.info(\"Blocking 1sec...\");\n        Helpers.sleepMillis(1000);\n        log.info(\"Ended blocking\");\n\n        return \"Hello\";\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part02SimpleOperators.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Helpers;\nimport io.reactivex.Flowable;\nimport io.reactivex.Single;\nimport org.junit.Test;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Random;\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author sbalamaci\n */\npublic class Part02SimpleOperators implements BaseTestObservables {\n\n    /**\n     * Delay operator - the Thread.sleep of the reactive world, it's pausing for a particular increment of time\n     * before emitting the whole range events which are thus shifted by the specified time amount.\n     *\n     * The delay operator uses a Scheduler {@see Part06Schedulers} by default, which actually means it's\n     * running the operators and the subscribe operations on a different thread, which means the test method\n     * will terminate before we see the text from the log. That is why we use the CountDownLatch waiting for the\n     * completion of the stream.\n     *\n     */\n    @Test\n    public void delayOperator() {\n        log.info(\"Starting\");\n\n        CountDownLatch latch = new CountDownLatch(1);\n        Flowable.range(0, 2)\n                .doOnNext(val -> log.info(\"Emitted {}\", val))\n                .delay(5, TimeUnit.SECONDS)\n                .subscribe(\n                        tick -> log.info(\"Tick {}\", tick),\n                        (ex) -> log.info(\"Error emitted\"),\n                        () -> {\n                            log.info(\"Completed\");\n                            latch.countDown();\n                        });\n\n        Helpers.wait(latch);\n    }\n\n    /**\n     * Timer operator waits for a specific amount of time before it emits an event and then completes\n     */\n    @Test\n    public void timerOperator() {\n        log.info(\"Starting\");\n        Flowable<Long> flowable = Flowable.timer(5, TimeUnit.SECONDS);\n        subscribeWithLogOutputWaitingForComplete(flowable);\n    }\n\n\n\n    @Test\n    public void delayOperatorWithVariableDelay() {\n        log.info(\"Starting\");\n        Flowable<Integer> flowable = Flowable.range(0, 5)\n                                    .doOnNext(val -> log.info(\"Emitted {}\", val))\n                                    .delay(val -> Flowable.timer(val * 2, TimeUnit.SECONDS));\n        subscribeWithLogOutputWaitingForComplete(flowable);\n    }\n\n    /**\n     * Periodically emits a number starting from 0 and then increasing the value on each emission\n     */\n    @Test\n    public void intervalOperator() {\n        log.info(\"Starting\");\n        Flowable<Long> flowable = Flowable.interval(1, TimeUnit.SECONDS)\n                                    .take(5);\n\n        subscribeWithLogOutputWaitingForComplete(flowable);\n    }\n\n    /**\n     * scan operator - takes an initial value and a function(accumulator, currentValue). It goes through the events\n     * sequence and combines the current event value with the previous result(accumulator) emitting downstream the\n     * the function's result for each event(the initial value is used for the first event).\n     */\n    @Test\n    public void scanOperator() {\n        Flowable<Integer> numbers = Flowable.just(3, 5, -2, 9)\n                .scan(0, (totalSoFar, currentValue) -> {\n                    log.info(\"totalSoFar={}, emitted={}\", totalSoFar, currentValue);\n                    return totalSoFar + currentValue;\n                });\n\n        subscribeWithLog(numbers);\n    }\n\n    /**\n     * reduce operator acts like the scan operator but it only passes downstream the final result\n     * (doesn't pass the intermediate results downstream) so the subscriber receives just one event\n     */\n    @Test\n    public void reduceOperator() {\n        Single<Integer> numbers = Flowable.just(3, 5, -2, 9)\n                .reduce(0, (totalSoFar, val) -> {\n                    log.info(\"totalSoFar={}, emitted={}\", totalSoFar, val);\n                    return totalSoFar + val;\n                });\n        subscribeWithLog(numbers);\n    }\n\n    /**\n     * collect operator acts similar to the reduce() operator, but while the reduce() operator uses a reduce function\n     * which returns a value, the collect() operator takes a container supplie and a function which doesn't return\n     * anything(a consumer). The mutable container is passed for every event and thus you get a chance to modify it\n     * in this collect consumer function\n     */\n    @Test\n    public void collectOperator() {\n        Single<List<Integer>> numbers = Flowable.just(3, 5, -2, 9)\n                .collect(ArrayList::new, (container, value) -> {\n                    log.info(\"Adding {} to container\", value);\n                    container.add(value);\n                    //notice we don't need to return anything\n                });\n        subscribeWithLog(numbers);\n    }\n\n    /**\n     * repeat resubscribes to the observable after it receives onComplete\n     */\n    @Test\n    public void repeat() {\n        Flowable<Integer> random = Flowable.defer(() -> {\n                                Random rand = new Random();\n                                return Flowable.just(rand.nextInt(20));\n                            })\n                            .repeat(5);\n\n        subscribeWithLogOutputWaitingForComplete(random);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part03MergingStreams.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Helpers;\nimport com.balamaci.rx.util.Pair;\nimport io.reactivex.Flowable;\nimport io.reactivex.Single;\nimport org.junit.Test;\n\nimport java.util.concurrent.CompletableFuture;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Operators for working with multiple streams\n *\n *\n */\npublic class Part03MergingStreams implements BaseTestObservables {\n\n    /**\n     * Zip operator operates sort of like a zipper in the sense that it takes an event from one stream and waits\n     * for an event from another other stream. Once an event for the other stream arrives, it uses the zip function\n     * to merge the two events.\n     * <p>\n     * This is an useful scenario when for example you want to make requests to remote services in parallel and\n     * wait for both responses before continuing.\n     * <p>\n     * Zip operator besides the streams to zip, also takes as parameter a function which will produce the\n     * combined result of the zipped streams once each stream emitted it's value\n     */\n    @Test\n    public void zipUsedForTakingTheResultOfCombinedAsyncOperations() {\n        Single<Boolean> isUserBlockedStream = Single.fromFuture(CompletableFuture.supplyAsync(() -> {\n            Helpers.sleepMillis(200);\n            return Boolean.FALSE;\n        }));\n        Single<Integer> userCreditScoreStream = Single.fromFuture(CompletableFuture.supplyAsync(() -> {\n            Helpers.sleepMillis(2300);\n            return 200;\n        }));\n\n        Single<Pair<Boolean, Integer>> userCheckStream = Single.zip(isUserBlockedStream, userCreditScoreStream,\n                Pair::new);\n        subscribeWithLogOutputWaitingForComplete(userCheckStream);\n    }\n\n    /**\n     * Implementing a periodic emitter, by waiting for a slower stream to emit periodically.\n     * Since the zip operator need a pair of events, the slow stream will work like a timer by periodically emitting\n     * with zip setting the pace of emissions downstream.\n     */\n    @Test\n    public void zipUsedToSlowDownAnotherStream() {\n        Flowable<String> colors = Flowable.just(\"red\", \"green\", \"blue\");\n        Flowable<Long> timer = Flowable.interval(2, TimeUnit.SECONDS);\n\n        Flowable<String> periodicEmitter = Flowable.zip(colors, timer, (key, val) -> key);\n\n        subscribeWithLogOutputWaitingForComplete(periodicEmitter);\n    }\n\n\n    /**\n     * Merge operator combines one or more stream and passes events downstream as soon\n     * as they appear\n     * <p>\n     * The subscriber will receive both color strings and numbers from the Observable.interval\n     * as soon as they are emitted\n     */\n    @Test\n    public void mergeOperator() {\n        log.info(\"Starting\");\n\n        Flowable<String> colors = periodicEmitter(\"red\", \"green\", \"blue\", 2, TimeUnit.SECONDS);\n\n        Flowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS)\n                .take(5);\n\n        Flowable flowable = Flowable.merge(colors, numbers);\n        subscribeWithLogOutputWaitingForComplete(flowable);\n    }\n\n    /**\n     * Concat operator appends another streams at the end of another\n     * The ex. shows that even the 'numbers' streams should start early, the 'colors' stream emits fully its events\n     * before we see any 'numbers'.\n     * This is because 'numbers' stream is actually subscribed only after the 'colors' complete.\n     * Should the second stream be a 'hot' emitter, its events would be lost until the first one finishes\n     * and the seconds stream is subscribed.\n     */\n    @Test\n    public void concatStreams() {\n        log.info(\"Starting\");\n        Flowable<String> colors = periodicEmitter(\"red\", \"green\", \"blue\", 2, TimeUnit.SECONDS);\n\n        Flowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS)\n                .take(4);\n\n        Flowable observable = Flowable.concat(colors, numbers);\n        subscribeWithLogOutputWaitingForComplete(observable);\n    }\n\n    /**\n     * combineLatest pairs events from multiple streams, but instead of waiting for an event\n     * from other streams, it uses the last emitted event from that stream\n     */\n    @Test\n    public void combineLatest() {\n        log.info(\"Starting\");\n\n        Flowable<String> colors = periodicEmitter(\"red\", \"green\", \"blue\", 3, TimeUnit.SECONDS);\n        Flowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS)\n                .take(4);\n        Flowable combinedFlowables = Flowable.combineLatest(colors, numbers, Pair::new);\n\n        subscribeWithLogOutputWaitingForComplete(combinedFlowables);\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part04HotPublishers.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Helpers;\nimport io.reactivex.Observable;\nimport io.reactivex.observables.ConnectableObservable;\nimport io.reactivex.subjects.PublishSubject;\nimport io.reactivex.subjects.ReplaySubject;\nimport io.reactivex.subjects.Subject;\nimport org.junit.Test;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.ScheduledExecutorService;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author sbalamaci\n */\npublic class Part04HotPublishers implements BaseTestObservables {\n\n    /**\n     * We've seen that with 'cold publishers', whenever a subscriber subscribes, each subscriber will get\n     * it's version of emitted values independently\n     *\n     * Subjects keep reference to their subscribers and allow 'multicasting' to them.\n     *\n     *  for (Disposable<T> s : subscribers.get()) {\n     *     s.onNext(t);\n     *  }\n\n     *\n     * Subjects besides being traditional Observables you can use the same operators and subscribe to them,\n     * are also an Observer, meaning you can invoke subject.onNext(value) from different parts in the code,\n     * which means that you publish events which the Subject will pass on to their subscribers.\n     *\n     * Observable.create(subscriber -> {\n     *      subscriber.onNext(val);\n     * })\n     * .map(...)\n     * .subscribe(...);\n     *\n     * With Subjects you can call onNext from different parts of the code:\n     * Subject<Integer> subject = ReplaySubject.create()\n     *                              .map(...);\n     *                              .subscribe(); //\n     *\n     * ...\n     * subject.onNext(val);\n     * ...\n     * subject.onNext(val2);\n     *\n     * ReplaySubject keeps a buffer of events that it 'replays' to each new subscriber, first he receives a batch of missed\n     * and only later events in real-time.\n     *\n     * PublishSubject - doesn't keep a buffer but instead, meaning if another subscriber subscribes later, it's going to loose events\n     */\n\n    @Test\n    public void replaySubject() {\n        Subject<Integer> subject = ReplaySubject.createWithSize(50);\n\n//        Runnable pushAction = pushEventsToSubjectAction(subject, 10);\n//        periodicEventEmitter(pushAction, 500, TimeUnit.MILLISECONDS);\n\n        pushToSubject(subject, 0);\n        pushToSubject(subject, 1);\n\n        CountDownLatch latch = new CountDownLatch(2);\n        log.info(\"Subscribing 1st\");\n        subject.subscribe(val -> log.info(\"Subscriber1 received {}\", val), logError(), logComplete(latch));\n\n        pushToSubject(subject, 2);\n\n        log.info(\"Subscribing 2nd\");\n        subject.subscribe(val -> log.info(\"Subscriber2 received {}\", val), logError(), logComplete(latch));\n        pushToSubject(subject, 3);\n\n        subject.onComplete();\n\n        Helpers.wait(latch);\n    }\n\n    private void pushToSubject(Subject<Integer> subject, int val) {\n        log.info(\"Pushing {}\", val);\n        subject.onNext(val);\n    }\n\n    @Test\n    public void publishSubject() {\n        Subject<Integer> subject = PublishSubject.create();\n\n        Helpers.sleepMillis(1000);\n        log.info(\"Subscribing 1st\");\n\n        CountDownLatch latch = new CountDownLatch(2);\n        subject\n                .subscribe(val -> log.info(\"Subscriber1 received {}\", val), logError(), logComplete(latch));\n\n        Helpers.sleepMillis(1000);\n        log.info(\"Subscribing 2nd\");\n        subject.subscribe(val -> log.info(\"Subscriber2 received {}\", val), logError(), logComplete(latch));\n        Helpers.wait(latch);\n    }\n\n\n    /**\n     * Because reactive stream specs mandates that events should be ordered(cannot emit downstream two events simultaneously)\n     * it means that it's illegal to call onNext,onComplete,onError from different threads.\n     *\n     * To make this easy there is the .toSerialized() operator that wraps the Subject inside a SerializedSubject\n     * which basically just calls the onNext,.. methods of the wrapped Subject inside a synchronized block.\n     */\n    @Test\n    public void callsToSubjectMethodsMustHappenOnSameThread() {\n        Subject<Integer> subject = PublishSubject.create();\n\n        CountDownLatch latch = new CountDownLatch(1);\n\n        Subject<Integer> serializedSubject = subject.toSerialized();\n        subject.subscribe(logNext(), logError(), logComplete(latch));\n\n        new Thread(() -> serializedSubject.onNext(1), \"thread1\").start();\n        new Thread(() -> serializedSubject.onNext(2), \"thread2\").start();\n        new Thread(() -> serializedSubject.onComplete(), \"thread3\").start();\n\n        Helpers.wait(latch);\n    }\n\n\n    /**\n     * ConnectableObservable is a special kind of Observable that when calling .subscribe()\n     * it just keeps a reference to its subscribers, it only subscribes once the .connect() method is called\n     */\n    @Test\n    public void sharingResourcesBetweenSubscriptions() {\n        ConnectableObservable<Integer> connectableObservable = Observable.<Integer>create(subscriber -> {\n            log.info(\"Inside create()\");\n\n            /* A JMS connection listener example\n               Just an example of a costly operation that is better to be shared **/\n\n            /* Connection connection = connectionFactory.createConnection();\n              Session session = connection.createSession(true, AUTO_ACKNOWLEDGE);\n              MessageConsumer consumer = session.createConsumer(orders);\n              consumer.setMessageListener(subscriber::onNext); */\n\n            subscriber.setCancellable(() -> log.info(\"Subscription cancelled\"));\n\n            log.info(\"Emitting 1\");\n            subscriber.onNext(1);\n\n            log.info(\"Emitting 2\");\n            subscriber.onNext(2);\n\n            subscriber.onComplete();\n        }).publish(); //calling .publish makes an Observable a ConnectableObservable\n\n        log.info(\"Before subscribing\");\n        CountDownLatch latch = new CountDownLatch(2);\n\n        /* calling .subscribe() bellow doesn't actually subscribe, but puts them in a list to actually subscribe\n           when calling .connect() */\n        connectableObservable\n                .take(1)\n                .subscribe((val) -> log.info(\"Subscriber1 received: {}\", val), logError(), logComplete(latch));\n\n        connectableObservable\n                .subscribe((val) -> log.info(\"Subscriber2 received: {}\", val), logError(), logComplete(latch));\n\n\n        //we need to call .connect() to trigger the real subscription\n        log.info(\"Now connecting to the ConnectableObservable\");\n        connectableObservable.connect();\n\n        Helpers.wait(latch);\n    }\n\n    /**\n     * We can get away with having to call ourselves .connect(), by using\n     */\n    @Test\n    public void autoConnectingWithFirstSubscriber() {\n        ConnectableObservable<Integer> connectableObservable = Observable.<Integer>create(subscriber -> {\n            log.info(\"Inside create()\");\n\n            //simulating some listener that produces events after\n            //connection is initialized\n            ResourceConnectionHandler resourceConnectionHandler = new ResourceConnectionHandler() {\n                @Override\n                public void onMessage(Integer message) {\n                 log.info(\"Emitting {}\", message);\n                 subscriber.onNext(message);\n                }\n            };\n\n            resourceConnectionHandler.openConnection();\n\n            subscriber.setCancellable(resourceConnectionHandler::disconnect);\n        }).publish();\n\n        Observable<Integer> observable = connectableObservable.autoConnect();\n\n        CountDownLatch latch = new CountDownLatch(2);\n        observable\n                .take(5)\n                .subscribe((val) -> log.info(\"Subscriber1 received: {}\", val), logError(), logComplete(latch));\n        Helpers.sleepMillis(1000);\n\n        observable\n                .take(2)\n                .subscribe((val) -> log.info(\"Subscriber2 received: {}\", val), logError(), logComplete(latch));\n\n        Helpers.wait(latch);\n    }\n\n    /**\n     * Even the above .autoConnect() can be improved\n     */\n    @Test\n    public void refCountTheConnectableObservableAutomaticSubscriptionOperator() {\n        ConnectableObservable<Integer> connectableObservable = Observable.<Integer>create(subscriber -> {\n            log.info(\"Inside create()\");\n\n            //simulating some listener that produces events after\n            //connection is initialized\n            ResourceConnectionHandler resourceConnectionHandler = new ResourceConnectionHandler() {\n                @Override\n                public void onMessage(Integer message) {\n                    log.info(\"Emitting {}\", message);\n                    subscriber.onNext(message);\n                }\n            };\n            resourceConnectionHandler.openConnection();\n\n            subscriber.setCancellable(resourceConnectionHandler::disconnect);\n        }).publish();\n\n        Observable<Integer> observable = connectableObservable.refCount();\n        //publish().refCount() equals share()\n\n        CountDownLatch latch = new CountDownLatch(2);\n        observable\n                .take(5)\n                .subscribe((val) -> log.info(\"Subscriber1 received: {}\", val), logError(), logComplete(latch));\n\n        Helpers.sleepMillis(1000);\n\n        log.info(\"Subscribing 2nd\");\n        //we're not seeing the code inside .create() re-executed\n        observable\n                .take(2)\n                .subscribe((val) -> log.info(\"Subscriber2 received: {}\", val), logError(), logComplete(latch));\n\n        Helpers.wait(latch);\n\n        //Previous Subscribers all unsubscribed, subscribing another will trigger the execution of the code\n        //inside .create()\n        latch = new CountDownLatch(1);\n        log.info(\"Subscribing 3rd\");\n        observable\n                .take(1)\n                .subscribe((val) -> log.info(\"Subscriber3 received: {}\", val), logError(), logComplete(latch));\n        Helpers.wait(latch);\n    }\n\n\n\n\n    private ScheduledExecutorService periodicEventEmitter(Runnable action,\n                                                          int period, TimeUnit timeUnit) {\n        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);\n        scheduledExecutorService.scheduleAtFixedRate(action, 0, period, timeUnit);\n\n        return scheduledExecutorService;\n    }\n\n\n    private abstract class ResourceConnectionHandler {\n\n        ScheduledExecutorService scheduledExecutorService;\n\n        private int counter;\n\n        public void openConnection() {\n            log.info(\"**Opening connection\");\n\n            scheduledExecutorService = periodicEventEmitter(() -> {\n                counter ++;\n                onMessage(counter);\n            }, 500, TimeUnit.MILLISECONDS);\n        }\n\n        public abstract void onMessage(Integer message);\n\n        public void disconnect() {\n            log.info(\"**Shutting down connection\");\n            scheduledExecutorService.shutdown();\n        }\n    }\n\n    /*    private Runnable pushEventsToSubjectAction(Subject<Integer> subject, int maxEvents) {\n        return () -> {\n            if(counter == maxEvents) {\n                subject.onComplete();\n                return;\n            }\n\n            counter ++;\n\n            log.info(\"Emitted {}\", counter);\n            subject.onNext(counter);\n        };\n    }*/\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part05AdvancedOperators.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Pair;\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.reactivex.flowables.GroupedFlowable;\nimport org.junit.Test;\n\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * @author sbalamaci\n */\npublic class Part05AdvancedOperators implements BaseTestObservables {\n\n    @Test\n    public void buffer() {\n        Flowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS);\n\n        Flowable<List<Long>> delayedNumbersWindow = numbers\n                .buffer(5);\n\n        subscribeWithLog(delayedNumbersWindow);\n    }\n\n    @Test\n    public void simpleWindow() {\n        Flowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS);\n\n        Flowable<Long> delayedNumbersWindow = numbers\n                .window(5)\n                .flatMap(window -> window.doOnComplete(() -> log.info(\"Window completed\")));\n\n        subscribeWithLog(delayedNumbersWindow);\n    }\n\n\n    @Test\n    public void window() {\n        Flowable<Long> numbers = Flowable.interval(1, TimeUnit.SECONDS);\n\n        Flowable<Long> delayedNumbersWindow = numbers\n                .window(10, 5, TimeUnit.SECONDS)\n                .flatMap(window -> window.doOnComplete(() -> log.info(\"Window completed\")));\n\n        subscribeWithLog(delayedNumbersWindow);\n    }\n\n    /**\n     * groupBy splits the stream into multiple streams with the key generated by the function passed as\n     * parameter to groupBy\n     */\n    @Test\n    public void groupBy() {\n        Flowable<String> colors = Flowable.fromArray(\"red\", \"green\", \"blue\",\n                \"red\", \"yellow\", \"green\", \"green\");\n\n        Flowable<GroupedFlowable<String, String>> groupedColorsStream = colors\n                .groupBy(val -> val); //identity function\n//                .groupBy(val -> \"length\" + val.length());\n\n        Flowable<Pair<String, Long>> colorCountStream = groupedColorsStream\n                .flatMap(groupedColor -> groupedColor\n                                            .count()\n                                            .map(count -> new Pair<>(groupedColor.getKey(), count))\n                                            .toFlowable()\n                );\n\n        subscribeWithLog(colorCountStream);\n    }\n\n    @Test\n    public void bufferWithLimitTriggeredByObservable() {\n        Observable<String> colors = Observable.fromArray(\"red\", \"green\", \"blue\",\n                \"red\", \"yellow\", \"#\", \"green\", \"green\");\n\n\n        colors.publish(p -> p.filter(val -> ! val.equals(\"#\"))\n                             .buffer(() -> p.filter(val -> val.equals(\"#\")))\n                )\n                .subscribe(list -> {\n            String listCommaSeparated = String.join(\",\", list);\n\n            log.info(\"List {}\", listCommaSeparated);\n        });\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part06Schedulers.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Helpers;\nimport io.reactivex.Flowable;\nimport io.reactivex.Observable;\nimport io.reactivex.Single;\nimport io.reactivex.schedulers.Schedulers;\nimport org.junit.Test;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * RxJava provides some high level concepts for concurrent execution, like ExecutorService we're not dealing\n * with the low level constructs like creating the Threads ourselves. Instead we're using a {@see rx.Scheduler} which create\n * Workers who are responsible for scheduling and running code. By default RxJava will not introduce concurrency\n * and will run the operations on the subscription thread.\n *\n * There are two methods through which we can introduce Schedulers into our chain of operations:\n * - <b>subscribeOn allows to specify which Scheduler invokes the code contained in the lambda code for Observable.create()\n * - <b>observeOn</b> allows control to which Scheduler executes the code in the downstream operators\n *\n * RxJava provides some general use Schedulers already implemented:\n *  - Schedulers.computation() - to be used for CPU intensive tasks. A threadpool equal to the numbers of available CPUs\n *  - Schedulers.io() - to be used for IO bound tasks\n *  - Schedulers.from(Executor) - custom ExecutorService\n *  - Schedulers.newThread() - always creates a new thread when a worker is needed. Since it's not thread pooled\n *  and always creates a new thread instead of reusing one, this scheduler is not very useful\n *\n * Although we said by default RxJava doesn't introduce concurrency, some operators that involve waiting like 'delay',\n * 'interval' need to run on a Scheduler, otherwise they would just block the subscribing thread.\n * By default **Schedulers.computation()** is used, but the Scheduler can be passed as a parameter.\n *\n * @author sbalamaci\n */\npublic class Part06Schedulers implements BaseTestObservables {\n\n    @Test\n    public void byDefaultRxJavaDoesntIntroduceConcurrency() {\n        log.info(\"Starting\");\n\n        Observable.<Integer>create(subscriber -> {\n            log.info(\"Someone subscribed\");\n            subscriber.onNext(1);\n            subscriber.onNext(2);\n\n            subscriber.onComplete();\n        })\n                .map(val -> {\n                    int newValue = val * 10;\n                    log.info(\"Mapping {} to {}\", val, newValue);\n//            Helpers.sleepMillis(2000);\n                    return newValue;\n                })\n                .subscribe(logNext());\n    }\n\n    @Test\n    public void subscribingThread() {\n        CountDownLatch latch = new CountDownLatch(1);\n\n        Observable<Integer> observable = Observable.<Integer>create(subscriber -> {\n            log.info(\"Someone subscribed\");\n            new Thread(() -> {\n                log.info(\"Emitting..\");\n                subscriber.onNext(1);\n                subscriber.onComplete();\n            }, \"custom-thread\").start();\n        })\n                .map(val -> {\n                    int newValue = val * 10;\n                    log.info(\"Mapping {} to {}\", val, newValue);\n\n                    return newValue;\n                });\n\n        observable.subscribe(logNext(), logError(), logComplete(latch));\n        Helpers.wait(latch);\n\n        log.info(\"Blocking Subscribe\");\n        observable.blockingSubscribe(logNext(), logError(), logComplete());\n        observable.observeOn(Schedulers.trampoline());\n        log.info(\"Got\");\n    }\n\n    /**\n     * subscribeOn allows to specify which Scheduler invokes the code contained in the lambda code for Observable.create()\n     */\n    @Test\n    public void testSubscribeOn() {\n        log.info(\"Starting\");\n\n        Observable<Integer> observable = Observable.create(subscriber -> { //code that will execute inside the IO ThreadPool\n            log.info(\"Starting slow network op\");\n            Helpers.sleepMillis(2000);\n\n            log.info(\"Emitting 1st\");\n            subscriber.onNext(1);\n\n            subscriber.onComplete();\n        });\n\n        observable = observable\n                .subscribeOn(Schedulers.io()) //Specify execution on the IO Scheduler\n                .map(val -> {\n                    int newValue = val * 10;\n                    log.info(\"Mapping {} to {}\", val, newValue);\n                    return newValue;\n                });\n\n        subscribeWithLogOutputWaitingForComplete(observable);\n    }\n\n\n    /**\n     * observeOn switches the thread that is used for the subscribers downstream.\n     * If we initially subscribedOn the IoScheduler we and we\n     * further make another .\n     */\n    @Test\n    public void testObserveOn() {\n        log.info(\"Starting\");\n\n        Flowable<Integer> observable = simpleFlowable()\n                .subscribeOn(Schedulers.io())\n                .observeOn(Schedulers.computation())\n                .map(val -> {\n                    int newValue = val * 10;\n                    log.info(\"Mapping {} to {}\", val, newValue);\n                    return newValue;\n                })\n                .observeOn(Schedulers.newThread());\n\n        subscribeWithLogOutputWaitingForComplete(observable);\n    }\n\n    /**\n     * Multiple calls to subscribeOn have no effect, just the first one will take effect, so we'll see the code\n     * execute on an IoScheduler thread.\n     */\n    @Test\n    public void multipleCallsToSubscribeOn() {\n        log.info(\"Starting\");\n\n        Flowable<Integer> observable = simpleFlowable()\n                .subscribeOn(Schedulers.io())\n                .subscribeOn(Schedulers.computation())\n                .map(val -> {\n                    int newValue = val * 2;\n                    log.info(\"Mapping new val {}\", newValue);\n                    return newValue;\n                });\n\n        subscribeWithLogOutputWaitingForComplete(observable);\n    }\n\n    @Test\n    public void blocking() {\n        log.info(\"Starting\");\n\n        Flowable<String> flowable = simpleFlowable()\n                .subscribeOn(Schedulers.io())\n                .subscribeOn(Schedulers.computation())\n                .map(val -> {\n                    String newValue = \"^^\" + val + \"^^\";\n                    log.info(\"Mapping new val {}\", newValue);\n                    Helpers.sleepMillis(500);\n                    return newValue;\n                });\n        flowable.blockingSubscribe(val -> log.info(\"Subscriber received {}\", val));\n        log.info(\"Finished blocking subscribe\");\n\n        Iterable<String> iterable = flowable.blockingIterable();\n        iterable.forEach(val -> log.info(\"Received {}\", val));\n        log.info(\"Finished blockingIterable\");\n    }\n\n    /**\n     * Controlling concurrency in flatMap\n     *\n     * By using subscribeOn in flatMap you can control the thread on which flapMap subscribes to the particular\n     * stream. By using a scheduler from a custom executor to which we allow a limited number of threads,\n     * we can also control how many concurrent threads are handling stream operations inside the flatMap\n     */\n    @Test\n    public void flatMapSubscribesToSubstream() {\n        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);\n\n        Flowable<String> observable = Flowable.range(1, 5)\n                .observeOn(Schedulers.io()) //Scheduler for multiply\n                .map(val -> {\n                    log.info(\"Multiplying {}\", val);\n                    return val * 10;\n                })\n                .flatMap(val -> simulateRemoteOp(val)\n                                    .subscribeOn(Schedulers.from(fixedThreadPool))\n                );\n\n        subscribeWithLogOutputWaitingForComplete(observable);\n    }\n\n    private Flowable<String> simulateRemoteOp(Integer val) {\n        return Single.<String>create(subscriber -> {\n            log.info(\"Simulate remote call {}\", val);\n            Helpers.sleepMillis(3000);\n            subscriber.onSuccess(\"***\" + val + \"***\");\n        }).toFlowable();\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part07FlatMapOperator.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Pair;\nimport io.reactivex.Flowable;\nimport io.reactivex.flowables.GroupedFlowable;\nimport io.reactivex.schedulers.Schedulers;\nimport org.junit.Test;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * The flatMap operator is so important and has so many different uses it deserves it's own category to explain\n * I like to think of it as a sort of fork-join operation because what flatMap does is it takes individual items\n * and maps each of them to an Observable(so it creates new Streams from each object) and then 'flattens' the\n * events from these Streams back into a single Stream.\n * Why this looks like fork-join because for each element you can fork some async jobs that emit some items before completing,\n * and these items are sent downstream to the subscribers as coming from a single stream\n *\n * RuleOfThumb 1: When you have an 'item' as parameter and you need to invoke something that returns an\n *                    Observable<T> instead of <T>, you need flatMap\n * RuleOfThumb 2: When you have Observable<Observable<T>> you probably need flatMap.\n *\n * @author sbalamaci\n */\npublic class Part07FlatMapOperator implements BaseTestObservables {\n\n    /**\n     * Common usecase when for each item you make an async remote call that returns a stream of items (an Observable<T>)\n     *\n     * The thing to notice that it's not clear upfront that events from the flatMaps 'substreams' don't arrive\n     * in a guaranteed order and events from a substream might get interleaved with the events from other substreams.\n     *\n     */\n    @Test\n    public void flatMap() {\n        Flowable<String> colors = Flowable.just(\"orange\", \"red\", \"green\")\n                .flatMap(colorName -> simulateRemoteOperation(colorName));\n\n        subscribeWithLogOutputWaitingForComplete(colors);\n    }\n\n    /**\n     * Inside the flatMap we can operate on the substream with the same stream operators like for ex count\n     */\n    @Test\n    public void flatMapSubstreamOperations() {\n        Flowable<String> colors = Flowable.just(\"orange\", \"red\", \"green\", \"blue\");\n\n        Flowable<Pair<String, Long>> colorsCounted = colors\n                .flatMap(colorName -> {\n                    Flowable<Long> timer = Flowable.interval(2, TimeUnit.SECONDS);\n\n                    return simulateRemoteOperation(colorName) // <- Still a stream\n                                    .zipWith(timer, (val, timerVal) -> val)\n                                    .count()\n                                    .map(counter -> new Pair<>(colorName, counter))\n                                    .toFlowable();\n                    }\n                );\n\n        subscribeWithLogOutputWaitingForComplete(colorsCounted);\n    }\n\n\n    /**\n     * Controlling the level of concurrency of the substreams.\n     * In the ex. below, only one of the substreams(the Observables returned by simulateRemoteOperation)\n     * is subscribed. As soon the substream completes, another substream is subscribed.\n     * Since only one substream is subscribed at any time, this way we don't see any values interleaved\n     */\n    @Test\n    public void flatMapConcurrency() {\n        Flowable<String> colors = Flowable.just(\"orange\", \"red\", \"green\")\n                .flatMap(colorName -> simulateRemoteOperation(colorName), 1);\n\n        subscribeWithLogOutputWaitingForComplete(colors);\n    }\n\n    /**\n     * As seen above flatMap might mean that events emitted by multiple streams might get interleaved\n     *\n     * concatMap operator acts as a flatMap with 1 level of concurrency which means only one of the created\n     * substreams(Observable) is subscribed and thus only one emits events so it's just this substream which\n     * emits events until it finishes and a new one will be subscribed and so on\n     */\n    @Test\n    public void concatMap() {\n        Flowable<String> colors = Flowable.just(\"orange\", \"red\", \"green\", \"blue\")\n                .subscribeOn(Schedulers.io())\n                .concatMap(val -> simulateRemoteOperation(val)\n                        .subscribeOn(Schedulers.io())\n                );\n\n        subscribeWithLogOutputWaitingForComplete(colors);\n    }\n\n    /**\n     * When you have a Stream of Streams - Observable<Observable<T>>\n     */\n    @Test\n    public void flatMapForProcessingAStreamOfStreams() {\n        Flowable<String> colors = Flowable.just(\"red\", \"green\", \"blue\",\n                \"red\", \"yellow\", \"green\", \"green\");\n\n        Flowable<GroupedFlowable<String, String>> groupedColorsStream = colors\n                                                                           .groupBy(val -> val);//grouping key\n                                                                           // is the String itself, the color\n\n        Flowable<Pair<String, Long>>\n                countedColors = groupedColorsStream\n                                        .flatMap(groupedFlow -> groupedFlow\n                                                                    .count()\n                                                                    .map(countVal -> new Pair<>(groupedFlow.getKey(), countVal))\n                                                                    .toFlowable()\n                                        );\n\n        subscribeWithLogOutputWaitingForComplete(countedColors);\n    }\n\n    /**\n     * 'switchIfEmpty' push some value(s) when the original stream just completes without 'returning' anything\n     */\n    @Test\n    public void flatMapSubstituteEmptyStream() {\n        Flowable<String> colors = Flowable.just(\"red\", \"\", \"blue\")\n                .flatMap(colorName -> simulateRemoteOperation(colorName)\n                                        .switchIfEmpty(Flowable.just(\"NONE\")));\n\n        subscribeWithLogOutputWaitingForComplete(colors);\n    }\n\n    /**\n     * flatMapIterable just takes as List and emits each of the elements\n     * as a stream.\n     */\n    @Test\n    public void flatMapIterable() {\n        Flowable<String> colors = Flowable.just(1)\n                .flatMapIterable(it -> generateColors());\n\n        subscribeWithLogOutputWaitingForComplete(colors);\n    }\n\n    private List<String> generateColors() {\n        return Arrays.asList(\"red\", \"green\", \"blue\");\n    }\n\n    @Test\n    public void switchMap() {\n        Flowable<String> colors = Flowable.interval(0,400, TimeUnit.MILLISECONDS)\n                .zipWith(Arrays.asList(\"EUR\", \"USD\", \"GBP\"), (it, currency) -> currency)\n                .doOnNext(ev -> log.info(\"Emitting {}\", ev))\n                .switchMap(currency -> simulateRemoteOperation(currency)\n                        .doOnSubscribe((subscription) -> log.info(\"Subscribed new\"))\n                        .doOnCancel(() -> log.info(\"Unsubscribed {}\", currency))\n                );\n\n        subscribeWithLogOutputWaitingForComplete(colors);\n    }\n\n\n    /**\n     * Simulated remote operation that emits as many events as the length of the color string\n     * @param color color\n     * @return stream of events\n     */\n    private Flowable<String> simulateRemoteOperation(String color) {\n        return Flowable.intervalRange(1, color.length(), 0, 200, TimeUnit.MILLISECONDS)\n                .map(iteration -> color + iteration);\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part08ErrorHandling.java",
    "content": "package com.balamaci.rx;\n\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport org.junit.Test;\n\nimport java.util.Random;\nimport java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Exceptions are for exceptional situations.\n * The Observable contract specifies that exceptions are terminal operations.\n * There are however operator available for error flow control\n */\npublic class Part08ErrorHandling implements BaseTestObservables {\n\n    private static final ConcurrentHashMap<String, AtomicInteger> attemptsMap = new ConcurrentHashMap<>();\n\n    /**\n     * After the map() operator encounters an error, it triggers the error handler\n     * in the subscriber which also unsubscribes from the stream,\n     * therefore 'yellow' is not even sent downstream.\n     */\n    @Test\n    public void errorIsTerminalOperation() {\n        Flowable<String> colors = Flowable.just(\"green\", \"blue\", \"red\", \"yellow\")\n                .map(color -> {\n                    if (\"red\".equals(color)) {\n                        throw new RuntimeException(\"Encountered red\");\n                    }\n                    return color + \"*\";\n                })\n                .map(val -> val + \"XXX\");\n\n        subscribeWithLog(colors);\n    }\n\n\n    /**\n     * The 'onErrorReturn' operator doesn't prevent the unsubscription from the 'colors'\n     * but it does translate the exception for the downstream operators and the final Subscriber\n     * receives it in the 'onNext()' instead in 'onError()'\n     */\n    @Test\n    public void onErrorReturn() {\n        Flowable<String> colors = Flowable.just(\"green\", \"blue\", \"red\", \"yellow\")\n                .map(color -> {\n                    if (\"red\".equals(color)) {\n                        throw new RuntimeException(\"Encountered red\");\n                    }\n                    return color + \"*\";\n                })\n                .onErrorReturn(th -> \"-blank-\")\n                .map(val -> val + \"XXX\");\n\n        subscribeWithLog(colors);\n    }\n\n\n    @Test\n    public void onErrorReturnWithFlatMap() {\n        //flatMap encounters an error when it subscribes to 'red' substreams and thus unsubscribe from\n        // 'colors' stream and the remaining colors still are not longer emitted\n        Flowable<String> colors = Flowable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n                .flatMap(color -> simulateRemoteOperation(color))\n                .onErrorReturn(throwable -> \"-blank-\"); //onErrorReturn just has the effect of translating\n\n        subscribeWithLog(colors);\n\n        log.info(\"*****************\");\n\n        //bellow onErrorReturn() is applied to the flatMap substream and thus translates the exception to\n        //a value and so flatMap continues on with the other colors after red\n        colors = Flowable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n                .flatMap(color -> simulateRemoteOperation(color)\n                                .onErrorReturn(throwable -> \"-blank-\")  //onErrorReturn doesn't trigger\n                        // the onError() inside flatMap so it doesn't unsubscribe from 'colors'\n                );\n\n        subscribeWithLog(colors);\n    }\n\n\n    /**\n     * onErrorResumeNext() returns a stream instead of an exception and subscribes to that stream instead,\n     * useful for example to invoke a fallback method that returns also a stream\n     */\n    @Test\n    public void onErrorResumeNext() {\n        Flowable<String> colors = Flowable.just(\"green\", \"blue\", \"red\", \"white\", \"blue\")\n                .flatMap(color -> simulateRemoteOperation(color)\n                        .onErrorResumeNext(th -> {\n                            if (th instanceof IllegalArgumentException) {\n                                return Flowable.error(new RuntimeException(\"Fatal, wrong arguments\"));\n                            }\n                            return fallbackRemoteOperation();\n                        })\n                );\n\n        subscribeWithLog(colors);\n    }\n\n    private Flowable<String> fallbackRemoteOperation() {\n        return Flowable.just(\"blank\");\n    }\n\n\n    /**\n     ************* Retry Logic ****************\n     ****************************************** */\n\n    /**\n     * timeout operator raises exception when there are no events incoming before it's predecessor in the specified\n     * time limit\n     * <p>\n     * retry() resubscribes in case of exception to the Observable\n     */\n    @Test\n    public void timeoutWithRetry() {\n        Flowable<String> colors = Flowable.just(\"red\", \"blue\", \"green\", \"yellow\")\n                .concatMap(color -> delayedByLengthEmitter(TimeUnit.SECONDS, color)\n                        .timeout(6, TimeUnit.SECONDS)\n                        .retry(2)\n                        .onErrorResumeNext(Flowable.just(\"blank\"))\n                );\n\n        subscribeWithLog(colors);\n        //there is also\n    }\n\n    /**\n     * When you want to retry based on the number considering the thrown exception type\n     */\n    @Test\n    public void retryBasedOnAttemptsAndExceptionType() {\n        Flowable<String> colors = Flowable.just(\"blue\", \"red\", \"black\", \"yellow\");\n\n        colors = colors\n                .flatMap(colorName -> simulateRemoteOperation(colorName, 2)\n                        .retry((retryAttempt, exception) -> {\n                            if (exception instanceof IllegalArgumentException) {\n                                log.error(\"{} encountered non retry exception \", colorName);\n                                return false;\n                            }\n                            log.info(\"Retry attempt {} for {}\", retryAttempt, colorName);\n                            return retryAttempt <= 3;\n                        })\n                        .onErrorResumeNext(Flowable.just(\"generic color\"))\n                );\n\n        subscribeWithLog(colors);\n    }\n\n    /**\n     * A more complex retry logic like implementing a backoff strategy in case of exception\n     * This can be obtained with retryWhen(exceptionObservable -> Observable)\n     * <p>\n     * retryWhen resubscribes when an event from an Observable is emitted. It receives as parameter an exception stream\n     * <p>\n     * we zip the exceptionsStream with a .range() stream to obtain the number of retries,\n     * however we want to wait a little before retrying so in the zip function we return a delayed event - .timer()\n     * <p>\n     * The delay also needs to be subscribed to be effected so we also need flatMap\n     */\n    @Test\n    public void retryWhenUsedForRetryWithBackoff() {\n        Flowable<String> colors = Flowable.just(\"blue\", \"green\", \"red\", \"black\", \"yellow\");\n\n        colors = colors.flatMap(colorName ->\n                    simulateRemoteOperation(colorName, 3)\n                        .retryWhen(exceptionStream -> exceptionStream\n                                .zipWith(Flowable.range(1, 3), (exc, attempts) -> {\n                                    //don't retry for IllegalArgumentException\n                                    if (exc instanceof IllegalArgumentException) {\n                                        return Flowable.error(exc);\n                                    }\n\n                                    if (attempts < 3) {\n                                        log.info(\"Attempt {}, waiting before retry\", attempts);\n                                        return Flowable.timer(2 * attempts, TimeUnit.SECONDS);\n                                    }\n                                    return Flowable.error(exc);\n                                })\n                                .flatMap(val -> val)\n                        )\n                        .onErrorResumeNext(Flowable.just(\"generic color\"))\n        );\n\n        subscribeWithLog(colors);\n    }\n\n    /**\n     * repeatWhen is identical to retryWhen only it responds to 'onCompleted' instead of 'onError'\n     */\n    @Test\n    public void testRepeatWhen() {\n        Flowable<Integer> remoteOperation = Flowable.defer(() -> {\n            Random random = new Random();\n            return Flowable.just(random.nextInt(10));\n        });\n\n        remoteOperation = remoteOperation.repeatWhen(completed -> completed\n                                                .delay(2, TimeUnit.SECONDS)\n                                          )\n                                .take(10);\n        subscribeWithLogOutputWaitingForComplete(remoteOperation);\n    }\n\n    private Flowable<String> simulateRemoteOperation(String color) {\n        return simulateRemoteOperation(color, Integer.MAX_VALUE);\n    }\n\n    private Flowable<String> simulateRemoteOperation(String color, int workAfterAttempts) {\n        return Flowable.create(subscriber -> {\n            AtomicInteger attemptsHolder = attemptsMap.computeIfAbsent(color, (colorKey) -> new AtomicInteger(0));\n            int attempts = attemptsHolder.incrementAndGet();\n\n            if (\"red\".equals(color)) {\n                checkAndThrowException(color, attempts, workAfterAttempts,\n                        new RuntimeException(\"Color red raises exception\"));\n            }\n            if (\"black\".equals(color)) {\n                checkAndThrowException(color, attempts, workAfterAttempts,\n                        new IllegalArgumentException(\"Black is not a color\"));\n            }\n\n            String value = \"**\" + color + \"**\";\n\n            log.info(\"Emitting {}\", value);\n            subscriber.onNext(value);\n            subscriber.onComplete();\n        }, BackpressureStrategy.BUFFER);\n    }\n\n    private void checkAndThrowException(String color, int attempts, int workAfterAttempts, Exception exception) {\n        if(attempts < workAfterAttempts) {\n            log.info(\"Emitting {} for {}\",  exception.getClass(), color);\n            throw new IllegalArgumentException(\"Black is not a color\");\n        } else {\n            log.info(\"After attempt {} we don't throw exception\", attempts);\n        }\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/Part09BackpressureHandling.java",
    "content": "package com.balamaci.rx;\n\nimport com.balamaci.rx.util.Helpers;\nimport io.reactivex.BackpressureOverflowStrategy;\nimport io.reactivex.BackpressureStrategy;\nimport io.reactivex.Flowable;\nimport io.reactivex.schedulers.Schedulers;\nimport io.reactivex.subjects.PublishSubject;\nimport org.junit.Test;\nimport org.reactivestreams.Subscriber;\nimport org.reactivestreams.Subscription;\n\nimport java.util.concurrent.CountDownLatch;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Backpressure is related to preventing overloading the subscriber with too many events.\n * It can be the case of a slow consumer that cannot keep up with the producer.\n * Backpressure relates to a feedback mechanism through which the subscriber can signal\n * to the producer how much data it can consume.\n *\n * However the producer must be 'backpressure-aware' in order to know how to throttle back.\n *\n * If the producer is not 'backpressure-aware', in order to prevent an OutOfMemory due to an unbounded increase of events,\n * we still can define a BackpressureStrategy to specify how we should deal with piling events.\n * If we should buffer(BackpressureStrategy.BUFFER) or drop(BackpressureStrategy.DROP, BackpressureStrategy.LATEST)\n * incoming events.\n *\n * @author sbalamaci\n */\npublic class Part09BackpressureHandling implements BaseTestObservables {\n\n\n\n    @Test\n    public void customBackpressureAwareFlux() {\n        Flowable<Integer> flux = new CustomRangeFlowable(5, 10);\n\n        flux.subscribe(new Subscriber<Integer>() {\n\n            private Subscription subscription;\n            private int backlogItems;\n\n            private final int BATCH = 2;\n            private final int INITIAL_REQ = 5;\n\n            @Override\n            public void onSubscribe(Subscription subscription) {\n                this.subscription = subscription;\n                backlogItems = INITIAL_REQ;\n\n                log.info(\"Initial request {}\", backlogItems);\n                subscription.request(backlogItems);\n            }\n\n            @Override\n            public void onNext(Integer val) {\n                log.info(\"Subscriber received {}\", val);\n                backlogItems--;\n\n                if (backlogItems == 0) {\n                    backlogItems = BATCH;\n                    subscription.request(BATCH);\n                }\n            }\n\n            @Override\n            public void onError(Throwable throwable) {\n                log.info(\"Subscriber encountered error\");\n            }\n\n            @Override\n            public void onComplete() {\n                log.info(\"Subscriber completed\");\n            }\n        });\n    }\n\n    /**\n     * We use BackpressureStrategy.DROP in create() to handle events that are emitted outside\n     * the request amount from the downstream subscriber.\n     *\n     * We see that events that reach the subscriber are those only 3 requested by the\n     * observeOn operator, the events produced outside of the requested amount\n     * are discarded (BackpressureStrategy.DROP).\n     *\n     * observeOn has a default request size from upstream of 128(system parameter {@code rx2.buffer-size})\n     *\n     */\n    @Test\n    public void createFlowableWithBackpressureStrategy() {\n        BackpressureStrategy backpressureStrategy =\n                BackpressureStrategy.DROP\n//              BackpressureStrategy.BUFFER\n//              BackpressureStrategy.LATEST\n//              BackpressureStrategy.ERROR\n                ;\n\n        Flowable<Integer> flowable = createFlowable(5, backpressureStrategy);\n\n        //we need to switch threads to not run the producer in the same thread as the subscriber(which waits some time\n        // to simulate a slow subscriber)\n        flowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n\n        subscribeWithSlowSubscriberAndWait(flowable);\n    }\n\n\n    /**\n     * There are operators for specifying backpressure strategy anywhere in the operators chain,\n     * not just at Flowable.create().\n     * - onBackpressureBuffer\n     * - onBackpressureDrop\n     * - onBackpressureLatest\n     * These operators request from upstream the Long.MAX_VALUE(unbounded amount) and then they buffer(onBackpressureBuffer)\n     * the events for downstream and send the events as requested.\n     *\n     * In the example we specify a buffering strategy in the example, however since the buffer is not very large,\n     * we still get an exception after the 8th value - 3(requested) + 5(buffer)\n     *\n     * We create the Flowable with BackpressureStrategy.MISSING saying we don't care about backpressure\n     * but let one of the onBackpressureXXX operators handle it.\n     *\n     */\n    @Test\n    public void bufferingBackpressureOperator() {\n        Flowable<Integer> flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureBuffer(5, () -> log.info(\"Buffer has overflown\"));\n\n        flowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n\n        subscribeWithSlowSubscriberAndWait(flowable);\n    }\n\n    /**\n     * We can opt for a variant of the onBackpressureBuffer, to drop events that do not fit\n     * inside the buffer\n     */\n    @Test\n    public void bufferingThenDroppingEvents() {\n        Flowable<Integer> flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureBuffer(5, () -> log.info(\"Buffer has overflown\"),\n                        BackpressureOverflowStrategy.DROP_OLDEST);\n\n        //we need to switch threads to not run the producer in the same thread as the subscriber(which waits some time\n        // to simulate a slow subscriber)\n        flowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n\n        subscribeWithSlowSubscriberAndWait(flowable);\n    }\n\n\n    /**\n     * Not only a slow subscriber triggers backpressure, but also a slow operator\n     * that slows down the handling of events and new request calls for new items\n     */\n    @Test\n    public void throwingBackpressureNotSupportedSlowOperator() {\n        Flowable<String> flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureDrop((val) -> log.info(\"Dropping {}\", val))\n                .observeOn(Schedulers.io(), false, 3)\n                .map(val -> {\n                    Helpers.sleepMillis(50);\n                    return \"*\" + val + \"*\";\n                });\n\n        subscribeWithLogOutputWaitingForComplete(flowable); //notice it's not the slowSubscribe method used\n    }\n\n    /**\n     * Backpressure operators can be added whenever necessary and it's not limited to\n     * cold publishers and we can use them on hot publishers also\n     */\n    @Test\n    public void backpressureWithHotPublisher() {\n        CountDownLatch latch = new CountDownLatch(1);\n\n        PublishSubject<Integer> subject = PublishSubject.create();\n\n        Flowable<Integer> flowable = subject\n                .toFlowable(BackpressureStrategy.MISSING)\n                .onBackpressureDrop(val -> log.info(\"Dropped {}\", val));\n\n        flowable = flowable.observeOn(Schedulers.io(), false, 3);\n\n        subscribeWithSlowSubscriber(flowable, latch);\n\n        for (int i = 1; i <= 10; i++) {\n            log.info(\"Emitting {}\", i);\n            subject.onNext(i);\n        }\n        subject.onComplete();\n\n        Helpers.wait(latch);\n    }\n\n    /**\n     * Chaining together multiple onBackpressureXXX operators doesn't actually make sense\n     * Using\n     *                 .onBackpressureBuffer(5)\n     *                 .onBackpressureDrop((val) -> log.info(\"Dropping {}\", val))\n     * is not behaving as maybe expected - buffer 5 values, and then dropping overflowing events-.\n     *\n     * Because onBackpressureDrop subscribes to the previous onBackpressureBuffer operator\n     * signaling its requesting Long.MAX_VALUE(unbounded amount) from it, the onBackpressureBuffer will never feel\n     * its subscriber is overwhelmed and never \"trigger\" meaning that the last onBackpressureXXX operator overrides\n     * the previous one.\n     *\n     * Of course for implementing an event dropping strategy after a full buffer, there is the special overrided\n     * version of onBackpressureBuffer that takes a BackpressureOverflowStrategy.\n     */\n    @Test\n    public void cascadingOnBackpressureXXXOperators() {\n        Flowable<Integer> flowable = createFlowable(10, BackpressureStrategy.MISSING)\n                .onBackpressureBuffer(5)\n                .onBackpressureDrop((val) -> log.info(\"Dropping {}\", val))\n                .observeOn(Schedulers.io(), false, 3);\n\n        subscribeWithSlowSubscriberAndWait(flowable);\n    }\n\n\n    /**\n     * Zipping a slow stream with a faster one also can cause a backpressure problem\n     */\n    @Test\n    public void zipOperatorHasALimit() {\n        Flowable<Integer> fast = createFlowable(200, BackpressureStrategy.MISSING);\n        Flowable<Long> slowStream = Flowable.interval(100, TimeUnit.MILLISECONDS);\n\n        Flowable<String> observable = Flowable.zip(fast, slowStream,\n                (val1, val2) -> val1 + \" \" + val2);\n\n        subscribeWithSlowSubscriberAndWait(observable);\n    }\n\n    @Test\n    public void backpressureAwareObservable() {\n        Flowable<Integer> flowable = Flowable.range(0, 10);\n\n        flowable = flowable\n                .observeOn(Schedulers.io(), false, 3);\n\n        subscribeWithSlowSubscriberAndWait(flowable);\n    }\n\n\n    private Flowable<Integer> createFlowable(int items,\n                                    BackpressureStrategy backpressureStrategy) {\n        return Flowable.<Integer>create(subscriber -> {\n            log.info(\"Started emitting\");\n\n            for (int i = 0; i < items; i++) {\n                if(subscriber.isCancelled()) {\n                    return;\n                }\n\n                log.info(\"Emitting {}\", i);\n                subscriber.onNext(i);\n            }\n\n            subscriber.onComplete();\n        }, backpressureStrategy);\n    }\n\n\n    private <T> void subscribeWithSlowSubscriberAndWait(Flowable<T> flowable) {\n        CountDownLatch latch = new CountDownLatch(1);\n        flowable.subscribe(logNextAndSlowByMillis(50), logError(latch), logComplete(latch));\n\n        Helpers.wait(latch);\n    }\n\n    private <T> void subscribeWithSlowSubscriber(Flowable<T> flowable, CountDownLatch latch) {\n        flowable.subscribe(logNextAndSlowByMillis(50), logError(latch), logComplete(latch));\n    }\n\n    private class CustomRangeFlowable extends Flowable<Integer> {\n\n        private int startFrom;\n        private int count;\n\n        CustomRangeFlowable(int startFrom, int count) {\n            this.startFrom = startFrom;\n            this.count = count;\n        }\n\n        @Override\n        public void subscribeActual(Subscriber<? super Integer> subscriber) {\n            subscriber.onSubscribe(new CustomRangeSubscription(startFrom, count, subscriber));\n        }\n\n        class CustomRangeSubscription implements Subscription {\n\n            volatile boolean cancelled;\n            boolean completed = false;\n            private int count;\n            private int currentCount;\n            private int startFrom;\n\n            private Subscriber<? super Integer> actualSubscriber;\n\n            CustomRangeSubscription(int startFrom, int count, Subscriber<? super Integer> actualSubscriber) {\n                this.count = count;\n                this.startFrom = startFrom;\n                this.actualSubscriber = actualSubscriber;\n            }\n\n            @Override\n            public void request(long items) {\n                log.info(\"Downstream requests {} items\", items);\n                for(int i=0; i < items; i++) {\n                    if(cancelled || completed) {\n                        return;\n                    }\n\n                    if(currentCount == count) {\n                        completed = true;\n                        if(cancelled) {\n                            return;\n                        }\n\n                        actualSubscriber.onComplete();\n                        return;\n                    }\n\n                    int emitVal = startFrom + currentCount;\n                    currentCount++;\n                    actualSubscriber.onNext(emitVal);\n                }\n            }\n\n            @Override\n            public void cancel() {\n                cancelled = true;\n            }\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/util/Helpers.java",
    "content": "package com.balamaci.rx.util;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * @author sbalamaci\n */\npublic class Helpers {\n\n    private static final Logger log = LoggerFactory.getLogger(Helpers.class);\n\n    public static void sleepMillis(int millis) {\n        try {\n            Thread.sleep(millis);\n        } catch (InterruptedException e) {\n            log.error(\"Interrupted Thread\");\n            throw new RuntimeException(\"Interrupted thread\");\n        }\n    }\n\n    public static void wait(CountDownLatch waitOn) {\n        try {\n            waitOn.await();\n        } catch (InterruptedException e) {\n            log.error(\"Interrupted waiting on CountDownLatch\");\n            throw new RuntimeException(\"Interrupted thread\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/balamaci/rx/util/Pair.java",
    "content": "package com.balamaci.rx.util;\n\npublic class Pair<T, V> {\n\n    private T key;\n    private V value;\n\n    public Pair(T key, V value) {\n        this.key = key;\n        this.value = value;\n    }\n\n    public T getKey() {\n        return key;\n    }\n\n    public V getValue() {\n        return value;\n    }\n\n    @Override\n    public String toString() {\n        return \"Pair{\" +\n                \"key=\" + key +\n                \", value=\" + value +\n                '}';\n    }\n}\n"
  },
  {
    "path": "src/test/resources/simplelogger.properties",
    "content": "# SLF4J's SimpleLogger configuration file\n# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.\n\n# Default logging detail level for all instances of SimpleLogger.\n# Must be one of (\"trace\", \"debug\", \"info\", \"warn\", or \"error\").\n# If not specified, defaults to \"info\".\norg.slf4j.simpleLogger.defaultLogLevel=info\n\n# Logging detail level for a SimpleLogger instance named \"xxxxx\".\n# Must be one of (\"trace\", \"debug\", \"info\", \"warn\", or \"error\").\n# If not specified, the default logging detail level is used.\n#org.slf4j.simpleLogger.log.xxxxx=\norg.slf4j.simpleLogger.log.ro.fortsoft.monitor=info\n\n# Set to true if you want the current date and time to be included in output messages.\n# Default is false, and will output the number of milliseconds elapsed since startup.\n#org.slf4j.simpleLogger.showDateTime=false\norg.slf4j.simpleLogger.showDateTime=true\n\n# The date and time format to be used in the output messages.\n# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.\n# If the format is not specified or is invalid, the default format is used.\n# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.\n#org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z\norg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss\n\n# Set to true if you want to output the current thread name.\n# Defaults to true.\n#org.slf4j.simpleLogger.showThreadName=true\n\n# Set to true if you want the Logger instance name to be included in output messages.\n# Defaults to true.\n#org.slf4j.simpleLogger.showLogName=true\n\n# Set to true if you want the last component of the name to be included in output messages.\n# Defaults to false.\norg.slf4j.simpleLogger.showShortLogName=true"
  }
]