Estoy jugando con proyecto del reactor y repositorios MongoDB reactivos. Tengo un código siguiente:
@Builder
@FieldDefaults(level = AccessLevel.PRIVATE)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Document
public class Person {
@Id
Integer id;
String name;
}
public interface ReactivePersonRepository extends ReactiveCrudRepository<Person, Integer> {
}
y la principal @SpringBootApplication
clase:
@SpringBootApplication
@EnableReactiveMongoRepositories
@RequiredArgsConstructor
public class ReactiveDatabaseApplication {
private final ReactivePersonRepository reactivePersonRepository;
public static void main(String[] args) {
SpringApplication.run(ReactiveDatabaseApplication.class, args);
}
@PostConstruct
public void postConstruct() {
Scheduler single = Schedulers.newSingle("single-scheduler");
IntStream.range(0, 10).forEach(i ->
Flux.just(Person.builder()
.id(i)
.name("PersonName")
.build())
.flatMap(personToSave -> {
System.out.println(String.format(
"Saving person from thread %s", Thread.currentThread().getName()));
return reactivePersonRepository.save(personToSave);
})
//.publishOn(single)
.flatMap(savedPerson -> {
System.out.println(String.format(
"Finding person from thread %s", Thread.currentThread().getName()));
return reactivePersonRepository.findById(savedPerson.getId());
})
//.publishOn(single)
.flatMap(foundPerson -> {
System.out.println(String.format(
"Deleting person from thread %s", Thread.currentThread().getName()));
return reactivePersonRepository.deleteById(foundPerson.getId());
})
//.publishOn(single)
.subscribeOn(single)
.subscribe(aVoid -> System.out.println(String.format(
"Subscription from thread %s", Thread.currentThread().getName()))));
}
}
La Flux::subscribeOn
descripción del método que dice:
Como tal, la colocación de este operador en cualquier lugar de la cadena también tendrá un impacto en la ejecución * contexto de señales onNext / OnError / onComplete desde el principio de la cadena hasta * la siguiente ocurrencia de un {@link publishOn (Scheduler) publishOn}
que es un poco confuso para mí, porque cuando no tengo ninguna publishOn
especificada en el procesamiento de la cadena, los valores impresos de nombres hilos son:
Ahorro de persona a partir de hilos de un solo programador-1 - como se esperaba
Encontrar a la persona a partir de hilos de rosca-13
Encontrar a la persona a partir de hilos de rosca-6
Encontrar a la persona a partir de hilos de rosca-15
persona Eliminación a partir de hilos de rosca-6
persona Eliminación a partir de hilos de rosca-5
persona Eliminación a partir de hilos de rosca-4
lo que no entiendo por qué. ¿No debería el planificador se especifica en el subscribeOn
método de utilizar para cada flatMap
ejecución?
Cuando me descomentar publishOn
líneas, todo lo que es ejecutado por el planificador solo dado, que es como se esperaba.
¿Alguien podría explicar por qué el único programador no es utilizada por flatMap
las operaciones, cuando no hay publishOn
?
Este ejemplo artificial puede hacer que sea más claro:
Scheduler single = Schedulers.newSingle("single-scheduler");
Flux.just("Bob")
.flatMap(x -> {
System.out.println(String.format(
"Saving person from thread %s", Thread.currentThread().getName()));
return Mono.just(x).publishOn(Schedulers.elastic());
})
.flatMap(x -> {
System.out.println(String.format(
"Finding person from thread %s", Thread.currentThread().getName()));
return Mono.just(x).publishOn(Schedulers.elastic());
})
.flatMap(x -> {
System.out.println(String.format(
"Deleting person from thread %s", Thread.currentThread().getName()));
return Mono.just(x).publishOn(Schedulers.elastic());
})
.subscribeOn(single)
.subscribe(aVoid -> System.out.println(String.format(
"Subscription from thread %s", Thread.currentThread().getName())));
Lo que dará algo similar a:
Saving person from thread single-scheduler-1
Finding person from thread elastic-2
Deleting person from thread elastic-3
Subscription from thread elastic-4
O, en otras palabras, su repositorio reactiva no está publicando en el mismo programador, y esta es la razón por la que se ve el comportamiento que haces. "Hasta la próxima ocurrencia de publishOn()
" no significa que la próxima vez que sus llamadas de código publishOn()
- también puede estar en cualquiera de los editores en ninguna de sus flatMap()
llamadas, que usted no tendrá ningún control sobre.