8. Publisher
Subscriber
1. subscribe
3. request(n) / cancel
2. onSubscribe (subscription)
4. onNext(data 1)
5. onComplete / onError
REACTIVE STREAMS API
Subscription
4. onNext(data …)
4. onNext(data n)
La source des
données
Le
consommateur
des données
9. IMPLÉMENTATION AVEC PROJET REACTOR
// Publisher de 0 à 1 élément
public abstract class Mono<T>
implements CorePublisher<T> {}
Flux.just("Hello", "How", "Are", "You?")
.doOnNext(System.out::println) // Data consumer
.doOnError(exc -> System.err.println("😭" + exc)) // Error consumer
.doOnComplete(() -> System.out.println("🎉")) // Complete consumer
.subscribe();
// Publisher de 0 à n éléments
public abstract class Flux<T>
implements CorePublisher<T> {}
10. Base de
données
Application
1. subscribe
3. request(n) / cancel
2. onSubscribe (subscription)
4. onNext(“R2D2”)
5. onComplete / onError
ET SI C’ETAIT UNE REQUETE…
Subscription
4. onNext(“C3PO”)
4. onNext(“BB-8”)
SELECT name FROM robot
11. REACTIVE API ET BASE DE DONNÉES
Driver Java v2
X DevAPI
(CompletableFuture)
SqlClient
ADBA
JDBC Reactive Extension
Reactive Driver
13. Définit une interface standard de
programmation réactive basée
sur les Reactive Streams,
destinée aux interactions avec
les bases de données
relationnelles. Reactive Streams
R2DBC SPI
R2DBC Driver X
16. UN PEU DE DÉPENDANCES POUR
COMMENCER…
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
</dependency>
20. public interface RobotRepository
extends ReactiveCrudRepository<Robot, Long> {
Flux<Robot> findByName(String name);
@Query("select distinct movie from robot")
Flux<String> getMovies();
}
CLASSE Reactive***Repository
21. @Transactional
public Mono<Void> create(Robot robot, Movie movie) {
return robotRepository.save(robot)
.then(movieRepository.save(movie))
.then();
}
ET AVEC UN ZESTE DE TRANSACTION!
public Mono<Void> create(Robot robot, Movie movie) {
TransactionalOperator rxtx = TransactionalOperator.create(reactiveTxManager );
return robotRepository.save(robot)
.then(movieRepository.save(movie))
.then()
.as(rxtx::transactional);
}
26. R2DBC PROXY
Librairie fournissant des callbacks
permettant d’accéder à l’exécution
des requêtes, pour:
- logging,
- métriques,
- traçage distribué,
- … R2DBC Driver
R2DBC Proxy
Application
27. R2DBC ET MULTI-TENANCY
Comment gérer plusieurs connexions selon un
contexte d’exécution ?
- AbstractR2dbcRouting : configuration des
différentes connexions
- AbstractRoutingConnectionFactory : fournit la
clé de sélection de la connexion
30. LOOM VA TUER LA PROGRAMMATION
REACTIVE ?
Movie getRobotFirstMovie(String robotName) {
Robot robot = repository.findRobotByName(robotName);
Movie movie = repository.findMovieById(robot.firstMovie);
return movie;
}
Movie getRobotFirstMovie(String robotName) {
CompletableFuture<Robot> robotFuture = CompletableFuture
.supplyAsync(() -> repository.findRobotByName(robotName));
CompletableFuture<Movie> movieFuture = robotFuture
.thenApplyAsync(robot -> repository.findMovieById(robot.firstMovie));
return movieFuture.get();
}
Mono<Movie> getFirstMovie(String robotName) {
return repository.findRobotByName(robotName)
.flatMap(robot -> repository.findMovieById(robot.firstMovie))
…. // Pleins de traitement: log, zip, map, …
.onErrorReturn(new Movie("Star Wars IV"));
}
?
@RunOnVirtualThread
31. LOOM VA TUER LA PROGRAMMATION
REACTIVE ?
Peut-être… ou pas
32. EN RÉSUMÉ …
Qu’a-t-on vu ?
- Initiative plus qu’intéressante pour standardiser l’accès aux bases de
données relationnelles en mode réactif
- Il y a aussi des transactions, du batch, des entity callbacks, de
l’observability, …
- Support de la communauté (clients, drivers, …)
- On peut faire du R2DBC sans aucun autre framework, mais ça va être
un peu roots :)
Mais il reste du boulot !
- Des frameworks en cours de mises à jour (Liquibase, …)
- Spring : pas de support des relations dans les entités :(
35. D’UN SYSTÈME SYNCHRONE ET
BLOQUANT…
Thread de traitement Thread bloqué !
Worker
thread
Hyper simplifié :)
Poursuite du traitement
36. … À UN SYSTÈME ASYNCHRONE ET
NON BLOQUANT !
Traitement d’une requête
Événement (tâche à réaliser avec
callback)
Invocation callback
Event loop
Traitement tâche
Modèle “Event Loop”
Événement
(résultat traitement tâche)
Worker
threads