Skip to content

Instantly share code, notes, and snippets.

@sats17
Last active January 1, 2024 05:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sats17/06cb0e6106affc5aa6d88cb3319d6fa7 to your computer and use it in GitHub Desktop.
Save sats17/06cb0e6106affc5aa6d88cb3319d6fa7 to your computer and use it in GitHub Desktop.
=======================================================================================================
=======================================================================================================
All-about-reactive-programming-java
=======================================================================================================
=======================================================================================================
Reactive programming is a paradigm that can be used to implement building blocks, therefore its scope is within components/services.
EDA, being an architectural style, is all about the interaction between components/services.
1) Worker threads vs Libraries which provides non-blocking call, how are they linked ?
1.1)Worker threads come into the picture in reactive programming when you need to perform potentially blocking operations,
like accessing a database, file I/O, or making a network request using non-reactive libraries.
1.2)In such cases, it's important to offload these blocking operations to worker threads to prevent them from blocking the main I/O threads,
which would negatively impact the responsiveness and scalability of your application.
1.3) Most reactive libraries provide mechanisms to offload blocking operations to worker threads.
For example, in SmallRye Mutiny (used in Quarkus), you can use methods like .runSubscriptionOn(executor) or .emitOn(executor) to
offload the execution of specific parts of the pipeline to a worker thread:
1.4) Third party libraries provides this event loop logic within themselves, like 2nd question. If we cannot use worker thread, then write
logic for own event loop.
2) How existing event loops like webclient event loop or redis event loop makes call non blocking ?
2.1) The Vert.x event loop does not block and wait for the Redis GET call to complete. Instead, it uses asynchronous, non-blocking I/O operations to communicate with Redis. Here's the sequence of events when the Vert.x event loop performs a Redis GET call:
2.2) The Vert.x event loop sends the GET request to Redis using a non-blocking I/O operation. The request is sent without waiting for the response, allowing the event loop to continue processing other events and tasks.
2.3) When the Redis server processes the GET request and sends the response back, the response is received by the underlying I/O system (e.g., the operating system's networking layer).
2.4) The Vert.x event loop is notified that there is a new incoming response. This notification is typically implemented using asynchronous I/O mechanisms provided by the operating system, such as epoll (on Linux), kqueue (on BSD and macOS), or IOCP (on Windows).
2.5) Upon receiving the notification, the Vert.x event loop processes the response, parses it, and invokes the appropriate callback or event handler associated with the original GET request.
The application code, such as the callback or event handler, processes the response and takes appropriate action, like updating the application state or returning the result to the client.
Throughout this entire process, the Vert.x event loop never blocks or waits for the Redis GET call to complete. It utilizes asynchronous, non-blocking I/O operations to ensure that it can continue processing other events and tasks while waiting for the Redis response.
This design allows the event loop to handle a large number of concurrent connections and requests efficiently, providing high concurrency and scalability for your application.
3) How event loop and reactive project makes main thread and worker thread do it's work in async way ?
In a reactive programming model like WebFlux, the flow typically involves the following steps:
1. **Main Thread Initiates Operation**: The main thread initiates an operation, such as making a request to a database or an external API.
2. **Offloading to Worker Thread**: The framework offloads the execution of the operation to a worker thread. This allows the main thread to continue processing other tasks or handling incoming requests without being blocked.
3. **Asynchronous Operation**: The worker thread performs the asynchronous, non-blocking operation (e.g., a database query). Instead of waiting for the operation to complete, the worker thread can be utilized for other tasks or incoming requests during this time.
4. **Callback Mechanism or Reactive Streams**: When the asynchronous operation is completed, a callback mechanism or reactive streams are used to handle the result. This can involve notifying the worker thread that the data is available.
5. **Worker Thread Continues or Signals Main Thread**: The worker thread, upon completion of the operation, can either continue with its own tasks or signal the main thread that the data is ready.
6. **Main Thread Receives Data**: Upon receiving the notification, the main thread can retrieve the data and continue with the necessary processing. This can involve additional business logic or sending a response to the client.
By using this non-blocking and asynchronous approach, the system can efficiently handle a large number of concurrent operations without the need for a dedicated thread per operation. It promotes better resource utilization and responsiveness in scenarios where there are potentially many I/O operations.
1) In the observer pattern, the observers are aware of the Subject.
The Subject maintains a record of the Observers.
Whereas, in publisher-subscriber, publishers and subscribers don’t need to know each other.
They simply communicate with the help of message queues or a broker.
2) In the publisher-subscriber pattern, components are loosely coupled as opposed to the observer pattern.
3) The observer pattern is mostly implemented synchronously, i.e. the Subject calls the appropriate method of all
its observers when an event occurs. The publisher-subscriber pattern is mostly implemented asynchronously (using a message queue).
4) The observer pattern needs to be implemented in a single-application address space.
On the other hand, the publisher-subscriber pattern is more of a cross-application pattern.
Ref = https://betterprogramming.pub/observer-vs-pub-sub-pattern-50d3b27f838c#:~:text=In%20the%20observer%20pattern%2C%20the,message%20queues%20or%20a%20broker.
-- ReactiveStream interfaces are provided by java to use.
There are multiple implementations are there Project reactor, RXJava etc.
ReactiveSteams -
imports = import org.reactivestreams.*;
* Reactive streams list of interfaces provided.
1) Publisher -
public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
2) Subscriber -
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
3) Subscription -
public interface Subscription {
public void request(long n);
public void cancel();
}
4) Processor -
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {
}
# What is this ‘specific propagation of change’?
Here’s a real-life example. Say, it’s Friday and John wants to spend this evening with his friend Bob, scarfing pizza and watching one of the Star Wars episodes. Let’s outline the options he has.
John finishes his work. Then goes and orders the pizza, waits till it’s done.
Then picks up his friend. And finally (with Bob and pizza) makes it home and gets
down to the movie. It will be the sync approach and it will be way too long, so that
probably John will have wanted to call the thing off by that time.
John orders his pizza online, phones Bob, invites him to come. He heads home, has
his pizza delivered and starts watching the movie (and eating the pizza) without waiting
for Bob to show up. That is what can happen with the async approach.
John orders pizza, phones Bob, invites him to come, heads home, and gets his pizza delivered.
But this time, he waits until Bob comes and only after that he turns the movie on.
This is what the reactive approach is about. You wait till all async actions (changes)(eventloop) are completed and
then proceed with further actions.
how servlet3.0 traditional vs servlet3.1 async works = ref link - https://dzone.com/articles/servlet-31spring-mvc-non-blocking-io
if we have servlet and mvc stack in async then why should we use webflux/reactive stack = https://dzone.com/articles/understanding-spring-reactiveintroducing-spring-we = spring servlet is async but for backward compatibility some of the code they made as blocking which can be use in our application hence they created seperate stack.
1) Java Streams are pull-based with terminal operator. Java Streams can be used only once.
Java Streams can run in sequential or in parallel. Java Streams do not have time-related variants of methods
2) Reactive Streams are push-based using subscriber. Reactive Streams can be used many times.
They run in one thread or in another one. They have time-related variants of methods.
Reactive Streams is effectively push-based. It has a single mode of operation, which works like a pull-based system when the subscriber is slower and a push-based system when the subscriber is faster.
1) How subscriber works in webflux -> Webflux generally perform autosubscribe for you when you return a publisher(Mono/Flux) from controller.
At that time internally webflux will do autosubscribe. There is a method where you can do subscribe by yourself. But according to publisher
interface when you subscribe a publisher you need to pass a subscriber. So in this case we aren't passing any subscriber this subscriber
creation part is taken care by webflux. The reactor.core.publisher.LambdaSubscriber is a private class that is actually create a subscriber.
And there is other overloaded methods which takes the consumer, which is nothing but webflux takes inner items from flux or mono and using those
it creates a subscribe.
Also, you can create your own subscriber(By implementing subscriber interface) and pass it it subscribe method as parameter.
2) Flatmap for flux -> Flatmap is basically Transform the elements emitted by this Flux asynchronously into Publishers,
then flatten these inner publishers into a single Flux through merging,which allow them to interleave.
3) Webflux flow
request->reactive(servlet/netty)->reactiveprogram(my-api-code)->reactiverestapicall(webclient)->thirdpartyservices(externalmicroservices)
Here data will come from request, initially data will be passed through reactive components like
webclient,my-api-code or reactive(servlet)
4) My observation on event stream of server site events in webflux using db -
I have created flux that will return events after 1 seconds of gap, Then I hit the API which matches suppose 20 items. So I will get all
items in 20 seconds, In between of those seconds I have ingested Items from outside of source so, for that query Items matches are 25. and in
the middle of 10th second I have ingested but still I receivd total 20 items not 25. So my observation is this webflux fetchs all items
from db and this event stream release that item after 1 second gap
4) How using webflux or pub-sub pattern reactive approach was achieve for http call -
Step 1 - Event loop thread will come, this thread will collect all lazy actions as kind of definitions(From controller to repo). These action
will return publisher(Mono/Flux).
Step 2 - At last it will call a subscribe method and thread will be release. Action will be passed to internal threads and those will perform
all the action that is defined.
Step 3 - These publisher will call subscriber methods(Of course they can call, because in publisher interface we have subscriber instance)
. so according to error or response. Subscriber method will invoked.
Step 4 - Once all actions done, result will go to event queue and event loop will pick result and passed it to outside world.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment