Comment transformer un Mono en un véritable asynchrone (non réactif!) appel de la méthode?

0

La question

J'ai une méthode

@Service
public class MyService {
    public Mono<Integer> processData() {
        ... // very long reactive operation
    }
}

Dans le flux de programme normal, j'appelle cette méthode de manière asynchrone via un Kafka de l'événement.

Pour des fins de test, j'ai besoin d' exposer la méthode comme un service web, mais la méthode doit être exposée en tant que asynchrone: retour uniquement code HTTP 200 OK ("demande acceptée") et poursuivre le traitement des données en arrière-plan.

Est-il OK (= ne pas avoir tous les effets secondaires indésirables) juste pour appeler Mono#subscribe() et de retour de la méthode de contrôleur?

@RestController
@RequiredArgsConstructor
public class MyController {
    private final MyService service;

    @GetMapping
    public void processData() {
        service.processData()
            .subscribeOn(Schedulers.boundedElastic())
            .subscribe();
    }
}

Ou est-il mieux de faire comme ceci (ici, je suis confus par l'avertissement de l'Ide, peut-être le même que https://youtrack.jetbrains.com/issue/IDEA-276018 ?):

public Mono<Void> processData() {
    service.processData()
        .subscribeOn(Schedulers.boundedElastic())
        .subscribe(); // IntelliJ complains "Inappropriate 'subscribe' call" but I think it's a false alarm in my case(?)
    return Mono.empty();
}

Ou une autre solution?

2

La meilleure réponse

3

Est-il OK (= ne pas avoir tous les effets secondaires indésirables) juste pour appeler Mono#subscribe() et retour à partir de la méthode de contrôleur?

Il y a des effets secondaires, mais vous pouvez être ok vivant avec eux:

  • C'est vraiment le feu et oublier - ce qui signifie bien que vous ne serez jamais à être informés d'un succès (dont la plupart des gens à réaliser), vous aurez également jamais être averti en cas d'échec (qui a beaucoup moins de gens à réaliser.)
  • Si le processus se bloque pour une raison quelconque, que l'éditeur ne sera jamais complète, et vous n'aurez aucun moyen de le savoir. Puisque vous êtes en vous abonnant sur le délimitée élastique de pool de threads, il va également attacher l'un de ces fils indéfiniment trop.

Le premier point que vous avez peut-être l'affaire, ou vous pourriez voulez mettre un peu de journalisation des erreurs plus bas que réactif de la chaîne comme un effet secondaire d'une certaine manière donc, vous avez au moins une notification interne si quelque chose va mal.

Pour le deuxième point, je vous recommande de mettre un (généreux) délai d'attente sur votre appel de méthode donc, elle au moins est annulé s'il n'a pas terminé dans un temps de jeu, et n'est plus accroché autour de la consommation de ressources. Si vous êtes en cours d'exécution d'une tâche asynchrone, alors ce n'est pas un énorme problème qu'il va tout simplement de consommer un peu de mémoire. Si vous enchaînez un appel bloquant sur l'élastique planificateur puis ce qui est pire, cependant, que vous êtes en attachant un fil dans ce pool de threads indéfiniment.

Je voudrais aussi vous demander pourquoi vous devez utiliser la délimitée élastique planificateur à tous ici - il est utilisé pour l'emballage de blocage des appels, ce qui ne semble pas être le fondement de ce cas d'utilisation. (Pour être clair, si votre service est le blocage, alors vous devez absolument l'enrouler sur l'élastique planificateur - mais si non, alors il n'y a aucune raison de le faire.)

Enfin, cet exemple:

public Mono<Void> processData() {
    service.processData()
        .subscribeOn(Schedulers.boundedElastic())
        .subscribe();
    return Mono.empty();
}

...est un brillant exemple de ce que ne pas le faire, que vous êtes en train de créer une sorte de "imposteur méthode réactive" - quelqu'un peut très raisonnablement abonnez-vous à qui est revenu l'éditeur de la pensée, il sera complète lorsque le sous-jacent de l'éditeur complète, ce qui n'est évidemment pas ce qui se passe ici. À l'aide d'un void le type de retour et donc de ne pas revenir tout, c'est la chose correcte à faire dans ce scénario.

2021-11-23 16:54:58
1

Votre option avec le code suivant est réellement ok:

@GetMapping
public void processData() {
    service.processData()
        .subscribeOn(Schedulers.boundedElastic())
        .subscribe();
}

C'est effectivement ce que vous faites dans une @Scheduled méthode qui retourne simplement rien et vous souscrire explicitement à l' Mono ou Flux de sorte que les éléments sont émis.

2021-11-23 08:36:44

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................