Come trasformare un Mono in un vero asincrona (non reattiva!) chiamata di metodo?

0

Domanda

Ho un metodo

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

Nel normale flusso del programma, io chiamo questo metodo in modo asincrono tramite un Kafka evento.

Per scopi di test ho bisogno di esporre il metodo di servizio web, ma il metodo deve essere esposto come asincrona: restituzione del solo codice HTTP 200 OK ("richiesta accettata") e la continuazione del trattamento dei dati in background.

È OK (= non si hanno effetti collaterali indesiderati) e chiamare Mono#subscribe() e ritorno dal metodo controller?

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

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

O è meglio farlo (qui mi sono confuso con l'avviso da parte di IntelliJ, forse la stessa 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();
}

O qualche altra soluzione?

2

Migliore risposta

3

È OK (= non si hanno effetti collaterali indesiderati) e chiamare Mono#subscribe() e ritorno dal metodo controller?

Ci sono effetti collaterali, ma può essere ok a vivere con loro:

  • E ' veramente il fuoco e dimenticare - il che significa che, mentre si mai informati di un successo (che la maggior parte delle persone realizzare), potrete anche mai informati di un fallimento (che sono molto di meno la gente si rende conto.)
  • Se il processo si blocca per qualche ragione, che l'editore non sarà mai completa, e non avrete modo di conoscere. Dal momento che si sta sottoscrivendo il delimitata elastico threadpool, anche legare una di quelle limitata thread a tempo indeterminato troppo.

Il primo punto potrebbe essere un bene, o si potrebbe desiderare di mettere qualche errore di registrazione più in basso che reattiva a catena come un effetto collaterale, in qualche modo, così almeno ho una notifica interno, se qualcosa va storto.

Per il secondo punto mi consiglia di mettere un (generoso) timeout sul tuo metodo di chiamare così almeno viene annullato se non è stata completata in un tempo prestabilito, e non è più appeso intorno al consumo di risorse. Se si sta eseguendo un'attività asincrona, quindi questo non è un enorme problema, in quanto ti basta consumare un po ' di memoria. Se si sta avvolgendo una chiamata di blocco sull'elastico di pianificazione, quindi questo è di peggio però, come si sta legando un filo che threadpool a tempo indeterminato.

Mi piacerebbe anche la domanda, perché è necessario utilizzare il delimitata elastico di pianificazione a tutti qui - è utilizzato per il confezionamento di blocco chiamate, che non sembra essere il fondamento di questo caso d'uso. (Per essere chiari, se il vostro servizio è il blocco, quindi si dovrebbe assolutamente avvolgerlo in elastico di pianificazione - ma se poi non c'è nessun motivo per farlo.)

Infine, in questo esempio:

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

...è un brillante esempio di cosa non fare, come si sta creando una sorta di "impostore reattiva metodo" - qualcuno potrebbe ragionevolmente sottoscrivere restituito editore pensando che sarà completa quando il sottostante editore completa, che ovviamente non è quello che succede qui. Utilizzando un void tipo di ritorno e, quindi, non restituendo nulla è la cosa giusta da fare in questo scenario.

2021-11-23 16:54:58
1

La vostra opzione con il codice riportato di seguito è effettivamente ok:

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

Questo è in realtà ciò che si fa in un @Scheduled metodo che restituisce semplicemente nulla e in modo esplicito sottoscrivere il Mono o Flux in modo che gli elementi vengono emessi.

2021-11-23 08:36:44

In altre lingue

Questa pagina è in altre lingue

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