[[recipe-filestream]]
=== Building a simple File Stream

Let's start with a pure `Publisher` implementation, we'll use Reactor API afterwads to simplify the following example.
As `Publisher` you will have to take care about a lot of small things that should be tested against the *Reactive Streams* TCK module. The purpose is to understand what *Reactor* can do for you in such situation to avoid all this machinery. 

[IMPORTANT]
In theory, *Reactive Streams* won't buy you much in a scenario of File Read blocking consuming, single threaded, over a simple loop doing that. If the _sink_ endpoint is blocking you already have a form of backpressure since it won't read more than it sends. The point of such Reactive File Stream is when in between it and the consumer there is one or more boundaries to cross, a decoupling that can take the form of a queue or a ring buffer. You could envision this scenario where you want to keep reading while the consumer is sending so the next time it asks for data (after sending its previous one), the data *is already in-memory*. A sort of prefetching in other words.

.Build a lazy file read Publisher matching the Subscriber request
[source, java, indent=2]
----
Publisher<String> fileStream = new Publisher<String>() { // <1>
	@Override
	public void subscribe(final Subscriber<? super String> subscriber) {
		final File file = new File("settings.gradle"); // <2>

		try {
			final BufferedReader is = new BufferedReader(new FileReader(file)); // <2>

			subscriber.onSubscribe(new Subscription() {

				final AtomicBoolean terminated = new AtomicBoolean(false);

				@Override
				public void request(long n) {
					long requestCursor = 0l;
					try {
						String line;
						while ((requestCursor++ < n || n == Long.MAX_VALUE) // <3>
								&& !terminated.get()) { // <4>

							line = is.readLine();
							if (line != null) {
								subscriber.onNext(line);
							} else {
								if (terminate()) {
									subscriber.onComplete(); // <5>
								}
								return;
							}
						}
					} catch (IOException e) {
						if (terminate()) {
							subscriber.onError(e); // <6>
						}
					}
				}

				@Override
				public void cancel() {
					terminate();
				}

				private boolean terminate() {
					if (terminated.compareAndSet(false, true)) {
						try {
							is.close(); // <7>
						} catch (Exception t) {
							subscriber.onError(t);
						}
						return true;
					}
					return false;
				}
			});

		} catch (FileNotFoundException e) {
			Streams.<String, FileNotFoundException> fail(e)
				.subscribe(subscriber); // <8>
		}
	}
};

Streams.wrap(fileStream)
	.capacity(4L) // <9>
	.consumeOn( // <10>
		Environment.sharedDispatcher(),
		System.out::println,
		Throwable::printStackTrace,
		nothing -> System.out.println("## EOF ##")
);

----
<1> Implement a `Publisher`. We'll see in the next example how to be smart about it with core and stream
<2> Open a `File` cursor and reader by Subscriber to allow for replayability: It's a `Cold Stream`.
<3> Match the number of read lines with the demand and ignore the demand if special Long.MAX_VALUE escaping number is passed.
<4> Check before each possible `onNext()` if the Stream is not *cancelled*.
<5> Call `onComplete()` which set the state of the `Subscription` to *cancelled*, ignoring further terminal signal if any.
<6> Call `onError(e)` which set the state of the `Subscription` to *cancelled*, ignoring further terminal signal if any. 
<7> Close the file if the subscriber is not interested any more in the content (error, completion, cancel). 
<8> Create a failed `Stream` that only `onSubscribe()` the pass subscriber and `onError(e)` it.
<9> `capacity` will hint downstream operations (`consumeOn` here) to chunk requests 4 by 4.
<10> `consumeOn` takes an extra argument to run the requests on a dispatcher in addition to the 3 possible `Consumer` reacting to each type of signal.


.Obviously there are ways to make that code more efficient, but also do more with less. Let's take a look at Reactor alternative `PublisherFactory` from core module, which is used by `Streams.createWith()` methods from stream module as well.


.Build a lazy file read with Core PublisherFactory§ (from 2.0.2+) and compose with Stream API
[source, java]
----
final String filename = "settings.gradle";
Publisher<String> fileStream = PublisherFactory.create( 
	(n, sub) -> { // <1>
		String line;
		final BufferedReader inputStream = sub.context() // <2>		
		long requestCursor = 0l;
		while ((requestCursor++ < n || n == Long.MAX_VALUE) && !sub.isCancelled()) { // <3>

			try {
				line = inputStream.readLine();
				if (line != null) {
					sub.onNext(line);
				} else {
					sub.onComplete(); // <4>
					return;
				}
			}
			catch (IOException exc) {
				sub.onError(exc);
			}
		}
	}, 
	sub -> new BufferedReader(new FileReader(filename)), // <5>
	inputStream -> inputStream.close() // <6>
);

Streams
	.wrap(fileStream)
	.process(RingBufferProcessor.create())
	.capacity(4L)
	.consume(
		System.out::println,
		Throwable::printStackTrace,
		nothing -> System.out.println("## EOF ##")
);

----
<1> Implement a `BiConsumer` to react on every `Subscriber` request `Long` n. Any unchecked exception will trigger the terminal callback and `Subscriber.onError(e)`.
<2> The `Subscriber` passed in the callback is a `SubscriberWithContext` decorator allowing access to `context()`  populated on start
<3> Match the number of read lines with the demand and ignore the demand if special Long.MAX_VALUE escaping number is passed. Also use `SubscriberWithContext.isCancelled()` to check asynchronous cancel from `Subscribers` before each read.
<4> Call `onComplete()` which set the state of the `SubscriberWithContext` to *cancelled*, ignoring further terminal signal if any.
<5> Define a context once for a new `Subscriber` that will be available later for each request `SubscriberWithContext.context()` 
<6> Define a terminal callback once intercepting `cancel()`, `onComplete()` or `onError(e)`.

We can use `PublisherFactory`, or <<streams.adoc#streams-basics, Streams factories>> like `Streams.createWith()` to quickly achieve common use cases:

* Open IO once
* React on requests
* Handle shutdown gracefully

[[recipes-circuitbreaker]]
=== Building a Quick Circuit Breaker

In this other exercise, we will focus more on the composition power in your hands with *Reactor Stream* module. A classic use-case is to build self-healing data pipelines using the http://martinfowler.com/bliki/CircuitBreaker.html[Circuit Breaker Pattern] (maybe soon available in `Stream` API, maybe).

In this scenario, we want to keep alive a `Stream` even if errors might fly in. When a certain number of errors is reached, we want to stop consuming from the main _circuit_, the actual `Stream`. For a short period we will _trip_ the circuit and use a fallback publisher `Stream`. This fallback can actually be any sort of `Publisher`, we will just emit an alternative message. The point is to avoid new access to the failing `Stream` for a while and give it a chance to recover.

.Quick (and dirty) Circuit Breaker test
[source,java]
----
final Broadcaster<String> closeCircuit = Broadcaster.create(); // <1>
final Stream<String> openCircuit = Streams.just("Alternative Message"); // <2>

final Action<Publisher<? extends String>, String> circuitSwitcher = Streams.switchOnNext(); // <3>

final AtomicInteger successes = new AtomicInteger(); // <4>
final AtomicInteger failures = new AtomicInteger();

final int maxErrors = 3;

Promise<List<String>> promise = // <5>
		circuitSwitcher // <6>
			.observe(d -> successes.incrementAndGet()) // <7>
			.when(Throwable.class, error -> failures.incrementAndGet())
			.observeStart(s -> { // <8>
				
				System.out.println("failures: " + failures +
					 " successes:" + successes);

				if (failures.compareAndSet(maxErrors, 0)) { 
					circuitSwitcher.onNext(openCircuit); // <9>
					successes.set(0);
					
					Streams
						.timer(1)  // <10>
						.consume(ignore -> circuitSwitcher.onNext(closeCircuit));
				}
			})
			.retry() // <11>
			.toList(); // <5>

circuitSwitcher.onNext(closeCircuit); // <12>

closeCircuit.onNext("test1");
closeCircuit.onNext("test2");
closeCircuit.onNext("test3");
closeCircuit.onError(new Exception("test4"));
closeCircuit.onError(new Exception("test5"));
closeCircuit.onError(new Exception("test6"));
Thread.sleep(1500); // <13>
closeCircuit.onNext("test7");
closeCircuit.onNext("test8");
closeCircuit.onComplete();  // <14>
circuitSwitcher.onComplete();

System.out.println(promise.await());
Assert.assertEquals(promise.get().get(0), "test1");
Assert.assertEquals(promise.get().get(1), "test2");
Assert.assertEquals(promise.get().get(2), "test3");
Assert.assertEquals(promise.get().get(3), "Alternative Message");
Assert.assertEquals(promise.get().get(4), "test7");
Assert.assertEquals(promise.get().get(5), "test8");
----
<1> Create the main *hot* `Broadcaster` stream to send data later on.
<2> Create a simple fallback stream when sh*t hits the fan.
<3> Create a `SwitchAction` which is a `Processor` accepting new `Publisher` to consume data from.
<4> Prepare shared counters for successes and failures.
<5> Return a `Promise` from `Stream.toList()` to convert the `Stream` into an eventual `List`
<6> Consume data from the circuitSwitcher `Processor` proxy that will be updated depending on the failures number.
<7> Count success on every valid `onNext(String)` and count errors on every `Throwable` exception
<8> Monitor `onSubscribe(Subscription)` call which is called after successful stream start.
<9> If the number of error is _maxErrors_, trip the circuit by changing the current circuitSwitcher data source to the fallback one.
<10> Re-consume from the main stream in 1 Second by signalling circuitSwitcher with it.
<11> Keep retrying on any exception, which means Cancel / Re Subscribe. That's why we `observeStart()` as any error will trigger it.
<12> Start the circuitSwitcher with the main `Stream`
<13> Artificial wait to leave a chance to the timer to close the circuit,
<14> Double `onComplete()` the current main stream and the circuitSwitcher itself (otherwise they will hang for the missing `onComplete()`.


=== Building Efficient Data Pipelines

=== Building Non-Blocking MicroServices

=== Building CQRS-like Applications

=== Other Example Applications

[horizontal]
https://github.com/reactor/reactor-quickstart[Quickstart]::
An example application showing several ways to use basic components in Reactor.
https://github.com/reactor/reactor-samples[Samples]::
A simple sample application that demonstrates Reactor functionality in JUnit tests.

[horizontal]

[discrete]
==== Non Blocking Konami Code

If you made it that far, here a simple non blocking stream to scale up your Konami codes over websocket. Tell me about a reward... Don't forget to add *Netty* in your classpath along *reactor-net*.

[source,java]
----
final Processor<Integer, Integer> keyboardStream = RingBufferProcessor.create();

NetStreams.<String, String>httpServer(spec -> 
		spec
			.codec(StandardCodecs.STRING_CODEC)
			.listen(3000)
	)
	.ws("/", channel -> {
		System.out.println("Connected a websocket client: " + channel.remoteAddress());

		return Streams
			.wrap(keyboardStream)
			.skipWhile(key -> KeyEvent.VK_UP != key)
			.buffer(10, 1) // <1>
			.map(keys -> keys.size() == 10 &&
				keys.get(0) == KeyEvent.VK_UP &&
				keys.get(1) == KeyEvent.VK_UP &&
				keys.get(2) == KeyEvent.VK_DOWN &&
				keys.get(3) == KeyEvent.VK_DOWN &&
				keys.get(4) == KeyEvent.VK_LEFT &&
				keys.get(5) == KeyEvent.VK_RIGHT &&
				keys.get(6) == KeyEvent.VK_LEFT &&
				keys.get(7) == KeyEvent.VK_RIGHT &&
				keys.get(8) == KeyEvent.VK_B &&
				keys.get(9) == KeyEvent.VK_A
		)
		.map(isKonami -> isKonami ? "Konami!" : "Nah")
		.nest()
		.flatMap(konamis ->
			channel.writeWith(konamis)
		);
	})
	.start()
	.await();

keyboardStream.onNext(KeyEvent.VK_RIGHT);
keyboardStream.onNext(KeyEvent.VK_UP);
keyboardStream.onNext(KeyEvent.VK_UP);
keyboardStream.onNext(KeyEvent.VK_DOWN);
keyboardStream.onNext(KeyEvent.VK_DOWN);
keyboardStream.onNext(KeyEvent.VK_LEFT);
keyboardStream.onNext(KeyEvent.VK_RIGHT);
keyboardStream.onNext(KeyEvent.VK_LEFT);
keyboardStream.onNext(KeyEvent.VK_RIGHT);
keyboardStream.onNext(KeyEvent.VK_B);
keyboardStream.onNext(KeyEvent.VK_A);
keyboardStream.onNext(KeyEvent.VK_C);
keyboardStream.onComplete();

System.out.println(konamis.await());
----
<1> Note the `buffer(size, skip)` use, we want to evaluate all last 10 keys combinations, 10 by 10. That means we need to create a new list of 10 keys for every key.