presencial en CDMX • Para desarrolladores que no pueden asistir • Para expositores nacionales o internacionales • Esfuerzo paralelo a las actividades de JVM_MX • YOLO
datos asíncronos. • Flujo de datos (Data Stream): Una secuencia de valores • Modelo de programación basado en el principio de empujar (push) en lugar de obtener (pull). • Los valores se “emiten” cuando están listos, no cuando se solicitan de una forma no-bloqueante (non-blocking) • Se permite ejecutar operaciones en paralelo en lugar de forma serial.
Lleva a Reactive Programming al siguiente nivel. • Permute aplicar funciones al flujo de datos. • map, filter, zip, take, etc.. • Integra flujo de tiempo y los eventos de composición en la programación funcional.
• Colección de funciones útiles para hacer programación reactiva. • ReactiveX esta implementado en mas de 10 lenguajes. • RxJava es la implementación de ReactiveX, fue escrita por el equipo de Netflix
Observer: Escucha los valores emitidos (receiver) • El Observer se suscribe (escucha) al Observable • Los Observers reaccionan a cualquier elemento o secuencias de elementos que emita el Observable • Muchos Observers pueden suscribirse al mismo Observable.
necesita bloquear mientras espera que el Observable emita valores • El Observer espera a recibir valores cuando el Observable esta listo para emitirlos • Sobre la base de empuje (push) en lugar de obtener (pull)
en Java de ReactiveX de Microsoft • El API de Netflix la usa para hacer la capa de servicio completamente asíncrona. • El objetivo es la JVM no el lenguaje. • Existe soporte para Java, Groovy, Clojure, y Scala
• Flexible: Se puede usar para emitir: • Un valor escalar (network result) • Secuencia (elementos en una lista) • Flujos infinitos (sensores de clima) • Mitiga el callback hell: Fácilmente se puede transformar un flujo asíncrono en otro
con cada valor emitido 2. Invocar un método que regrese un Observable 3. Suscribirse el Observer al Observable. Esto le dice al Observable que tiene un subscriptor esperando a recibir valores cuando estén disponibles.
* {@link Observable} has finished sending * push-based notifications. * <p> * The {@link Observable} will not call * this method if it calls {@link #onError}. */ void onCompleted();
{@link Observable} * has experienced an error condition. * <p> * If the {@link Observable} calls this method, it * will not thereafter call {@link #onNext} or * {@link #onCompleted}. * * @param e * the exception encountered by the * Observable */ void onError(Throwable e);
indicar que ha fallado al obtener la información esperada o alguno otro problema. • Esto detiene al Observable y no hará mas invocaciones. • Envía la excepción que genero el problema.
new item to observe. * <p> * The {@link Observable} may call this method 0 or * more times. * <p> * The {@code Observable} will not call this method * again after it calls either {@link #onCompleted} * or {@link #onError}. * * @param t * the item emitted by the Observable */ void onNext(T t);
vez que el Observable emite un elemento. • Este método puede ser invocado cualquier número de veces (de cero a muchos). • Siempre seguido por onError o onComplete (pero no ambos)
lógica en el hilo del subscriptor? • ¿Tal vez delega parte del trabajo a otros hilos? • ¿Usará NIO? • ¿Tal vez es un actor? • ¿Devolverá datos de un cache? • ¡Al Observer no le importa!
for (int i = 0; i < 5; i++) { subscriber.onNext(i); } // Si olvidamos invocar onCompleted se // pueden crear Observables sin fin. subscriber.onCompleted(); } catch (Throwable cause) { subscriber.onError(cause); } });
más rápido de lo que el Observer puede procesarlos? • Cold Observable: • Emite una secuencia particular de elementos, puede empezar a emitirla cuando su Observer lo considere conveniente y a la tasa de entrega que el Observer desee, sin interferir la integridad de la secuencia. • Hot Observable: • Es un Observable que empieza a generar elementos inmediatamente cuando es creado. Los subscriptores pueden empezar a observar la secuencia de elementos emitidos a la mitad de la secuencia, empezando con el primer elemento emitido posterior al establecimiento de la subscripción. Dicho Observable emite elementos a su propio ritmo y es responsabilidad de los Observers mantener ese mismo ritmo.
discoveryClient.getInstances("service_id").stream() //Obtengo su URI remota (host:port) .map(serviceInstance -> serviceInstance.getUri().toString()) //Genera un Worker que hará el trabajo de pedirle //a cada instancia del servicio el archivo. //DownloadCacheWorker implementa java.util.concurrent.Callable .map(baseUrl -> new DownloadLocalCacheWorker(baseUrl, bucket, key)) //Genero un Future para hacerlo asíncrono .map(callable -> ((ThreadPoolTaskExecutor) taskExecutor).submit(callable)) //Lo convierto a Observable para facilitar //el manejo de errores .map(Observable::from) //Genero una lista de Observables .collect(Collectors.toList());
//Si algo falla al obtener el archivo del //servicio remoto, simplemente regreso null .onErrorReturn(throwable -> { log.warn("No se encontró algo", throwable); return null; }).doOnCompleted(() -> {}) //Descarto todos los null .filter(fileContent -> fileContent != null) //obtengo el primer resultado exitoso //(en teoría solo debe existir en un solo servidor) .firstOrDefault(null) //hago la llamada bloqueante .toBlocking() //aplico la lógica de manejo del archivo .subscribe(new DownloadLocalCacheObserver(response, key, notFound));