Stream Processing: Aplicación directa dentro de una arquitectura distribuida

PROYECTO FIN DE MASTER

MASTER UNIVERSITARIO EN SOFTWARE DE SISTEMAS DISTRIBUIDOS Y EMPOTRADOS

STREAM PROCESSING: APLICACIÓN DIRECTA DENTRO DE LA ARQUITECTURA DISTRIBUIDA DE UN DASHBOARD

Alumno DANIEL ENRIQUE GARCÍA CAFFERATA

Tutor SERGIO ARÉVALO VIÑUALES

2018

1 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

2 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

CONTENIDO Resumen...... 5 1. Capitulo I: Introducción...... 6 1.1 Introducción...... 6 1.2 Objetivos...... 7 2. Capitulo II: Estado del Arte...... 9 2.1 Sobre la arquitectura Stream Processing...... 9 2.2 La importancia de los logs...... 12 2.3 Procesadores en streaming...... 13 2.3.1 Apache Flink...... 13 2.3.2 Apache Storm...... 16 2.3.3 Apache Samza...... 18 2.3.4 Otras alternativas: PL/SQL...... 22 2.4 Herramientas de intermediación de mensajes...... 23 2.4.1 Apache Kafka...... 23 2.4.2 RabbitMQ...... 25 2.4.3 Apache DistributedLog...... 30 2.4.4 MSMQ...... 32 3. Capitulo III: Especificación de requisitos del software...... 34 3.1 Introducción...... 34 3.1.1 Propósito...... 34 3.1.2 Alcance...... 34 3.1.3 Definiciones, siglas y abreviaciones...... 35 3.1.4 Apreciación global...... 36 3.2 Descripción global...... 37 3.2.1 Perspectiva del producto...... 37 3.2.2 Funciones del producto...... 39 3.2.3 Características del usuario...... 43 3.2.4 Restricciones...... 43 3.2.5 Atención y dependencias...... 43 3.3 Requisitos específicos...... 43 3.3.1. Requisitos de desarrollo...... 43 3.3.2. Atributos del software...... 43

3 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

4. Capitulo IV: Arquitectura heredada...... 44 5. Capitulo V: Diseño de una nueva arquitectura...... 46 5.1 Requisitos...... 46 5.2 Elección de un procesador en streaming...... 48 5.3 Elección de una herramienta de intermediación de mensajes...... 49 5.4 Puesta en producción con MSMQ y PL/SQL...... 50 5.5 Solución con Kafka y Flink...... 52 6. Capitulo VI: Pruebas...... 55 6.1 Pruebas de rendimiento...... 55 7. Capitulo VII: Conclusiones...... 56 Referencias...... 58 ANEXOS...... 59 1. Instalación de Apache Flink y pequeña demo con Apache Kafka...... 59 2. Instalación de MSMQ y pequeña demo...... 65 Prerequisitos...... 65 Instalación...... 65 Una pequeña demo en MSMQ...... 66 3. Revisiones en SVN...... 70

4 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Resumen

Este documento describe la transformación de una aplicación de una empresa dedicada al sector ferroviario. Esta aplicación recoge en tiempo real datos de planificación de transporte ferroviario, los guarda en una base de datos y permite mostrarlos en un centro de mando (Dashboard). Debido a que la aplicación tiene que estar ejecutando todos los días del año y que el numero de trenes a planificar es muy alto ( 5000) tanto las escrituras como las lecturas son muy lentas. La transformación de este proyecto consistirá en adoptar técnicas de Stream Processing que permitan no solo desacoplar las escrituras de las lecturas sino también hacer más modular y escalable el posible crecimiento de la aplicación.

This documents describes the transformation of an application of a railway company. This software collects real-time data of railway plannification, saves it in a database and allows to show processed data in a web dashboard. Because of the need to execute this tool all the days and because of the number of trains to plan is very high, read and write operations are very slow. Transformation will consist to adopt Stream Processing techniques that will allow not only to decouple writes operations, but also to make it more modular and scalable the software evolution.

5 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

1. Capitulo I: Introducción

1.1 Introducción

Como parte de la cuarta revolución industrial, o como es habitual leerla: Industria 4.0, se incluye un área de estudio relacionada con el tratamiento de grandes volúmenes de datos y el aprovechamiento de los mismos en tiempo real. A esta área se le ha denominado Big Data y análisis de datos. Estos datos, pudiendo estar estructurados, no estructurados o semiestructurados son de un volumen de tal magnitud que las herramientas y técnicas de procesamiento convencionales no son capaces de procesarlas. Teniendo como punto neurálgico esta idea ha surgido un crisol de subapartados de estudio, estrategias, herramientas y paradigmas que se complementan unos a otros resolviendo distintos pequeños problemas.

No nos encontramos ante un problema tradicional donde se pueden utilizar detección de patrones, inferencia estadística, etc. Se tratan de verdaderos problemas ya no solo de interpretación, sino también técnicos: rendimiento, capacidad computacional, etc. Problemas técnico que en la última década han sido minimizados con los continuos avances nanotecnológicos.

En algún momento de la última década, las corporaciones empezaron a procesar ingentes cantidades de datos capturados en distintos procesos informáticos (por ejemplo, la visita de una página web como empezó a hacer Google Analytics). Hasta hace relativamente poco tiempo, estos datos capturados en distintos puntos no eran capaces de ser procesados y utilizados en tiempo real, sino que debían ser almacenados, para luego ser analizados en un proceso offline que podía tardar varios días.

Rápidamente, tras las primeras releases de Hadoop hace 6 años, los grandes departamentos de I+D han empezado a innovar hasta el punto de existir todo un ecosistema de herramientas software e ideas al rededor de estos conceptos.

Una de estas ideas, Stream Processing, se ha vuelto popular por su potencia a la par de simplicidad y practicidad. No es una idea nueva, es una idea rescatada de finales de los años 90s. Una idea sobre la que se basan muchas librerías software de las que se hablará en este documento: Flink, Storm, Kafka, etc. Y aunque su explicación en profundidad se postergará hasta el capítulo Estado del Arte, podemos resumirla

6 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

en que la idea es separar las escrituras y las lecturas que se realizan con el fin de ganar rendimiento en ambas operaciones, siempre hablando en términos de tiempo real.

Con el fin de explicar el concepto anterior, se introducirán dos software propietarios en escena: GoalRail(r), un software de planificación de planes de transporte del sector ferroviario interurbano y GS Dashboard, un software web con que se presentan y resumen datos de salida de GoalRail(r) en tiempo real.

Desde el inicio de desarrollo de GS Dashboard, se notó que la mayor problemática era como procesar tan ingente cantidad de datos en tiempo real y presentarlos en un módulo web. La idea con la que se empezó fue la de utilizar una base de datos tradicional, almacenar los datos y en tiempo de lectura intentar agregar todos los datos. GoalRail(r) se encargaría de publicar los datos que deberían verse en GS Dashboard. Sobre el papel todo funcionaba correctamente.

Meses después, y tras un primer intento de puesta en marcha, GS Dashboard tuvo que ser desconectado porque los tiempos de procesamiento tanto de escritura desde GoalRail(r) y lectura desde el navegador web eran impracticables. La arquitectura no era capaz de soportar tal trasiego de datos, y el usuario final no podía perder tanto tiempo en escribir y leer estos datos. ¿Cómo se resolvería esta situación a tiempo? ¿Como conseguiríamos no bloquear al usuario de GoalRail(r)? ¿Cómo conseguiríamos procesar 900 millones de registros al mostrar la web sin que la espera fuese agobiante?

En este trabajo de fin de máster se relatará cómo fue la transición de esta arquitectura clásica a un enfoque de Stream Processing, tras estudiar los pormenores teóricos de este útil paradigma. Estudiaremos también las distintas herramientas que se barajaron en el momento del diseño de la nueva arquitectura. Este trabajo concluirá después de hacer una comparativa de resultados para comprobar la hipótesis inicial: Stream Processing podía ser la respuesta a todas las interrogantes que surgieron en el equipo de desarrollo tras una desastrosa desconexión de GS Dashboard.

1.2 Objetivos

Los objetivos propuestos dentro de este Trabajo Fin de Máster son:

7 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

− Estudiar el estado del arte en Stream Processing

− Diseñar una nueva arquitectura para GS Dashboard con los conocimientos adquiridos de Stream Processing.

− Desarrollar e integrar los componentes dentro de la nueva arquitectura distribuida. − Adecuar el módulo web de GS Dashboard

− Realizar comparativas de rendimiento con una y otra arquitectura.

− Estudiar software de terceros (y actuales) dentro del mundo de Stream Processing.

8 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

2. Capitulo II: Estado del Arte

2.1 Sobre la arquitectura Stream Processing

Como hemos dicho anteriormente, el concepto de Stream Processing no es una novedad. Podemos remontarnos a finales de la década de 1990 donde encontraremos las primeras publicaciones al respecto. No obstante, lo que si que es una novedad es la popularidad que ha cobrado en la actualidad y la variedad de sectores donde es adoptado. No solo se trata de análisis estadísticos, es que podemos encontrarlo en aplicaciones bancarias, videojuegos, telecomunicaciones, redes sociales, ventas, etc.

Se empezará por recordar cuales fueron los inicios de Stream Processing para luego ir hacía el “dónde irá”.

Ilustración 1. Arquitectura Lambda

La arquitectura Lambda, ilustrada en la parte superior de este párrafo, fue una de las primeras implementaciones de Stream Processing. Consiste en 3 capas: por lotes, de velocidad y la que sirve datos. Los datos (1) vienen como entrada a la capa de velocidad (4) y por lotes (2), mientras que las aplicaciones que consumen datos (5) lo hacen de la capa que los sirve (3) que se encargará de hacer una combinación de los datos, mostrando una aproximación de los datos que serían los más actualizados.

9 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Los pros de esta arquitectura es que en su momento se consiguió reducir las latencias en la lectura, pero con un coste de implementación muy alto. Esta arquitectura supone mantener una misma lógica semántica del dato en capas separadas. Por la cantidad de módulos que se ven involucrados es una arquitectura muy cara en términos de mantenibilidad, desarrollo y depuración. Esta fue considerada la primera generación de Stream Processing.

Posteriormente, en la segunda generación, se realizaron mejoras en cuanto a la tolerancia a fallos, se aseguró la recepción y envío de eventos, etc. Sin embargo, los resultados finales seguían dependiendo de factores externos al dato en sí mismo. Por ejemplo, el orden de llegada de los eventos.

Actualmente, nos encontramos en la tercera generación de procesadores en streaming. Asuntos como el orden de llegada de los eventos ya no es un problema, se asegura que cada evento será procesado exactamente una vez en caso de fallo. Se han añadido funcionalidades extra, como poder actualizar la versión del procesador sin que se pierda el estado de la aplicación, aplicaciones que permiten gestionar los recursos como Hadoop YARN, etc.

Ilustración 2. Caso básico de agregación en un event stream

En contraposición a la arquitectura Lambda, la idea básica que nos propone Martin Kleppmann es que utilicemos una cola de eventos donde estén suscritos distintos procesos, donde al menos, uno de ellos agregará el dato y otro lo almacenará a modo de histórico (log), minimizando el tiempo de escritura. Más tarde, los

10 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

consumidores finales deberán leer el dato agregado, minimizando así el tiempo de lectura. Al haber utilizado una cola de eventos, se consigue evitar condiciones de carrera en el procesamiento de datos, los eventos serán procesados en orden secuencial. Esto nos da una seguridad extra que con Lambda no teníamos inicialmente.

En este caso, si existiese algún problema en la agregación podríamos reconstruir el estado final utilizando los datos históricos (log) como entrada. De hecho, una de las posibles operaciones (eliminar un dato), se apoya en esta mecánica de log histórico para reconstruir el estado final sin tenerlo en cuenta.

Una de las implementaciones más conocidas de las ideas descritas arriba, es la arquitectura Kappa, introducida por Jey Kreps, arquitecto líder en el área de infraestructura de datos online de Linkedin. Kappa es una simplificación, literal en palabras de Kreps, de Lambda, donde la capa batch desparece en favor de la capa de streaming.

Ilustración 3. Arquitectura Kappa

Esta implementación de Stream Processing se basa en la capacidad de almacenaje de Kafka, donde el reprocesamiento simplemente implica leer en la cola desde una posición distinta a la última. Evidentemente esta operación de reprocesamiento solo se hará cuando el código de la implementación de los procesadores en streaming cambie y haga falta reprocesar el output final.

Más adelante volveremos en detalle a a esta elección de Kafka como intermediador de mensajes, que no es en lo más mínimo accidental. Quizás el hecho de sustituir Kafka pueda ser lo más complejo en esta arquitectura, aunque podría utilizarse otras herramientas como soporte a la ordenación y al almacenaje con posibilidad de vuelta atrás que Kafka nos ofrece.

11 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Como procesador en streaming se utiliza Apache Samza, otro de los proyectos donde Kreps está involucrado. Aunque la implementación esté basada en Samza, no debería existir limitación tecnológica como para no elegir otra herramienta. El propio Kreps indica que podría utilizarse Storm en lugar de Samza.

2.2 La importancia de los logs

Las arquitecturas distribuidas en general, y las basadas en Stream Processing en particular, tienen un elemento en común demasiado importante como para no dedicarle un mínimo atención y estudio. Se trata de los logs, anglicismo para el español “tronco”, aunque hablando en un contexto informático la traducción más acertada sea registro histórico. Los logs son la base de muchos de los sistemas software que nos rodean, desde bases de datos NoSQL hasta el control de versiones. Su principal objetivo es saber qué es lo que ha ocurrido histórico, qué es lo que nos ha traído hasta éste último estado.

Los logs no solo son los que todo programador utiliza para verter en ellos lo que ha ocurrido en una aplicación, estos son la degeneración de un concepto mucho más antiguo, que tiene que ver más con la definición de bitácora que de un mero registro de errores de aplicación.

Podríamos decir que los logs son la abstracción más básica de almacenamiento de datos, donde los datos se añaden siempre al final y pueden identificarse inequívocamente por un número de secuencia u orden relativo. Una propiedad muy útil en sistemas distribuidos, no depender de ningún reloj.

En otro ámbitos informáticos, no solo el distribuido, el log también juega un rol muy importante. Por ejemplo, en las entrañas de las bases de datos, los logs cumplen el mismo cometido que nosotros perseguimos: ser capaces de saber el estado final antes de que ocurra una caída de algún componente del sistema distribuido. Este concepto también será importante en nuestra arquitectura, si el sistema se cae o falla, la única forma de recuperar el estado será reprocesando el log enteramente.

Nuestro mayor problema es mantener consistente el log distribuido entre los distintos nodos que interactuan en la red, los distintos problemas que pueden ocurrir y cómo controlarlos: particiones en la red, concurrencia, condiciones de carrera, etc. Quizás podríamos decir que todo se reduce en mantener el consenso entre todos los nodos

12 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

que mantienen el estado del log. Afortunadamente, de este problema se encargarán algunas herramientas dentro del capítulo de intermediación de mensajes que estudiaremos posteriormente.

2.3 Procesadores en streaming

Como hemos visto en el capítulo Estado del Arte se discuten distintas posibilidades en la elección de procesadores en streaming, componentes que nos permiten procesar, modificar, transformar y agregar la información en tiempo real. En este capítulo se pretende explicar sus diferencias, similitudes y conveniencias en distintas situaciones.

2.3.1 Apache Flink

Apache Flink es una plataforma de código abierto para procesamiento distribuido en batch o en stream. Provee un nucleo que es un motor de flujo de datos en streaming, que permite la distribución de la información, la comunicación y la tolerancia a fallos sobre flujos (streams) de datos.

Los bloques de programas más básicos en Flink son los Streams y Transformations. Conceptualmente los streams son flujos de registros de datos que potencialmente nunca acabarán, y una transformación es una operación sobre uno o más streams que dará como resultados uno o más streams de salida.

Las sentencias en Flink pueden ser representadas como simples flujos de datos. En la documentación podremos encontrar que los streams de entrada se llaman sources (fuentes) y los streams de salida se llaman sinks (sumideros).

13 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 4. Esquema de un programa en Flink

Los sources y los sinks pueden ser distintas tecnologías para las que Apache Flink tiene soporte en la sección de conectores de su documentación. Entre ellos podemos encontrar Apache Kafka, Apache Cassandra, Amazon Kinesis Streams, Elasticsearch, HDFS, RabbitMQ, Apache NiFi, Twiter Streaming API. A través de Apache Bahir podremos conectarnos con ActiveMQ, Flume, Redis, Akka y Netty. Como vemos, tiene un amplio soporte en cuanto a interoperabilidad.

Cuenta con soporte para JDBC, lo que unido a la Table API y sus Continuous Queries nos permite hacer procesamiento en streaming manteniendo persistentemente el resultado de la transformación.

Ilustración 5. Continuous queries en Apache Flink

14 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

En otras palabras esto nos permitiría leer el resultado desde una tabla donde se le indicara a las aplicaciones consumidoras el resultado consolidado, tal como nos sugiere el siguiente esquema:

Ilustración 6. Esquema de utilización de la salida de Flink con Continuous Queries

En cuanto al paralelismo, Apache Flink soporta el procesamiento distribuido, donde los procesos se podrán realizar en distintos hilos que posiblemente estén ubicados en otros nodos de la red, mientras que se asegura coherencia en la salida en el sumidero.

Además, posee un repertorio bastante amplio de operadores de transformación de alto nivel: Map, FlatMap, Filter, KeyBy, Reduce, Fold. Existe la posibilidad de definir operaciones de bajo nivel a través de interfaces como ProcessFunction.

El tiempo invertido en montar una pequeña demo con Apache Kafka y Apache Flink no fue mayor a dos horas. La documentación es acertada, aunque por ratos el usuario puede perder la noción con qué versión de Flink está trabajando (en ese sentido, saber a qué versión de Flink da soporte la documentación o el artículo puede llevar a error a un usuario que recién toma contacto).

La visualización que da la interfaz web es agradable, y aunque permite subir y ejecutar ficheros jar desde ella, el autor no fue capaz de ejecutarlo. La interfaz por linea de comandos es potente y no falla en este sentido.

En cuanto a rendimiento, Apache Flink es un contendiente potente, según lo declarado en su propio sitio web consigue mejores resultados que Apache Storm (otra herramienta de procesamiento en streaming) en sus comparativas.

15 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 7. Comparativa Flink - Storm

Sin embargo esta conclusión no es la misma si nos referimos a procesamiento en batch, que aunque no es parte del ámbito de este proyecto, es bastante más lento que otros oponentes como Apache Spark.

Se ha realizado una instalación básica de Apache Flink y resuelto la integración con Kafka en el “Anexo #1 - Instalación de Apache Flink y pequeña demo con Apache Kafka”.

2.3.2 Apache Storm

Apache Storm es una herramienta de procesamiento en streaming de código abierto. Según la documentación de Storm: “hacen que el procesamiento en streaming sea tan fácil como Hadoop MapReduce lo hizo para el procesamiento en batch”.

En Storm existen ocho conceptos clave:

1. Topologies: donde se concentra la lógica del procesador en streaming. Es una analogía a los jobs de MapReduce. Estas topologías, a diferencia de los jobs de MR, leen un origen de datos teóricamente ilimitado, y que solo se tiene si matamos el proceso. Las topologías son además, una agrupación de spouts y bolts, conceptos que repasaremos más adelante en este subapartado.

2. Streams: Concepto clave dentro de cualquier herramienta de procesado en streaming. Represente un flujo ilimitado de tuplas.

16 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

3. Spouts (canalón en español): Es un origen de streams en una topología. Este origen puede ser tan distinto como un topic de Kafka, o la de Twitter. Estos spouts pueden ser fiables o no fiables. Si lo que queremos es que el spout recuerde los mensajes que Storm no ha sido capaz de procesar, entonces necesitamos que sea fiable.

4. Bolts (tornillo en español): Es dónde ocurren todas las transformaciones en Apache Storm: filtrado, funciones, joins, comunicación con bases de datos, etc. De forma intuitiva, un bolt realiza una tarea, mientrás más compleja es nuestra tarea deberíamos trocearla en tantos más bolts.

5. Stream groupings: Hablando en clave de arquitectura distribuida, los grouping permiten definir cómo se distribuirán los streams entre los distintos tasks de cada bolt. Existen distintos tipos de grouping: podemos indicarle que sea aleatorio; por alguna clave, por ejemplo usuario; global, es decir que un solo task asuma todo el trabajo; directo, etc.

6. Reliability: Storm provee una capa que nos permite gestionar a menor nivel la confiabilidad de la entrega y procesamiento de mensajes a lo largo de todo el flujo de datos que definamos. Por ejemplo, nos permite modificar el timeout interno para considerar que un mensaje no se ha procesado, etc.

7. Tasks: A cada spout o bolt se le puede indicar un índice de paralelismo a lo largo del clúster. Cada tarea se corresponde con un hilo de ejecución .

8. Workers: Cada uno de ellos es una instancia JVM que ejecutan un subconjunto de tasks para la topología. Es decir, si existiese una topología con un índice de paralelismo de 200 y 25 workers disponibles, cada worker ejecutaría 4 tasks.

17 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 8. Esquema de alto nivel de Storm

Con la Ilustración 11. Esquema de alto nivel de Storm, se pretende dar una idea conceptual-gráfica de los spouts (grifos), streams (flechas), tuplas, bolts (rayos). Con una ilustración de este estilo es fácil notar que Storm es un framework mucho más complejo que muchos de los disponibles actualmente.

Familiarizarse con tantos conceptos, incrementa la curva de aprendizaje. Sin embargo, la granularidad tan fina que ofrece Storm puede ser crítica en la toma de decisiones en sistemas a medida.

2.3.3 Apache Samza

Al igual que otras herramientas que hemos estudiado en este apartado, Apache Samza es un framework de stream processing. Sus funciones más básicas incluyen: − Una API simple, y parecida a la forma de trabajar con Map Reduce. − Gestión de estado: Permite guardar una imagen del estado para poder ser restaurada a posteriori. − Tolerancia a particiones: Cuando una partición falla, Samza se encarga transparentemente de migrar las tareas a otra partición con Apache YARN. − Durabilidad: Samza usa Kafka para garantizar de que los mensajes llegarán en orden y que no se perderán. − Escalibidad − Interoperabilidad con otros sistemas

18 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

El esquema básico de un procesador escrito con Samza tiene como entrada input streams, y cómo salida output streams. Según la tecnología que escojamos para la intermediación de mensajes supondrán leer de uno u otro origen. Por ejemplo, si se tiene como intermediador a Kafka, estos streams serán un topic de Kafka.

Ilustración 9. Esquema básico de Samza Un job en Samza es código que realiza una transformación sobre un conjunto de streams de entrada, que insertará mensajes de salida en los output streams. Existe la posibilidad de trocear estos jobs en tasks, y los streams en partitions, con el fin de ganar escabilidad.

Las particiones en Samza es la división de un stream. En estas se mantiene el orden de los mensajes y la unicidad de los mismos. Cada mensaje dentro de la partición tiene un atributo único, llamado offset que lo identifica de los demás mensajes del stream. Cuando un mensaje se va a escribir en el stream, se escribe en solo uno de las particiones a partir de una clave (key) que asegura el escritor; por ejemplo, la clave puede ser el identificador del usuario, para que así, todos los mensajes de un mismo usuario estén en la misma partición.

Ilustración 10. Un stream particionado de Samza

19 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

De la misma forma, una task es la división de un job en Samza. Cada task consume de una partición para cada uno de los streams de entrada del job. El número de tasks la determina el número de particiones de un stream. No hay orden desde el el cual partición leer primero, esto permite que los tasks funcionen de forma independiente. Eso permite que el job entero sea realizado por un cluster coordinado por YARN, que es quien asigna un task a un nodo en la red distribuida.

Ilustración 11. Esquema de un job de Samza divido en dos tasks

A partir de estas abstracciones es posible componer gráficos de flujo más complejos donde los jobs son totalmente independientes unos de otros y dónde no interactuan dos jobs entre sí, sino que la interacción existente es job-stream.

Según la documentación del propio Samza, estos flujos de datos pueden ser cíclicos si quisiésemos, aunque en la representación inferior no ocurra.

20 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 12. Diagrama de flujo en Samza Es importante reseñar que estos términos que hemos repasado, son puramente términos lógicos. Es decir, un job o un stream no se corresponde con ningún elemento físico de CPU, memoria o HDD. Estas asignaciones se hacen a nivel de contenedores de UNIX (cgroups).

En cuanto a arquitectura, Samza está compuesto de tres capas, de forma análoga a MapReduce. En este caso, solo se mantendrá la capa de coordinación YARN, reemplazando el origen de los datos (que antes era HDFS), por Kafka, y dónde la capa de procesamiento la realiza el API de Samza, y no, como en el caso de Hadoop, MapReduce.

De una forma más gráfica, la pila de tecnologías es la siguiente:

Ilustración 13. Comparativa de arquitecturas entre Samza y Hadoop MR

21 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Sobre YARN y Kafka (que se describe en otro subapartado de este documento) se puede decir que aunque tienen propiedades interesantes y particulares, Samza puede trabajar sin ellos, es decir, con un sustituto de estos.

En general se puede decir que Apache Storm y Apache Samza son muy parecidos, comparten muchos conceptos que aunque nombren de forma distinta están presentes. Ambos proveen las mismas funcionalidades de alto nivel: un modelo de streams particionados, un entorno de ejecución distribuida, una API para el procesamiento en streaming, tolerancia a fallos, integración con Kafka y otros herramientas, etc.

En cuanto a las garantías de envío, Storm ofrece muchas más opciones, aunque el enfoque “at-least-one delivery”, es decir, que asegura que se enviará al menos una vez el mensaje. Storm ofrece otros dos modos: exactamente un envío y como mucho un envío.

En cuanto a la persistencia, Storm no ofrece ninguna ayuda en la gestión de la persistencia. Un bolt de storm puede mantener en memoria el estado, pero si el bolt se cae, el estado se pierde. Como parte de la API Trident de Storm, existe la posibilidad de llamar a bases de datos como Cassandra para guardar periodicamente el estado, sin embargo se convierte fácilmente en un cuello de botella en cuanto la cantidad de datos que estemos procesando supere los 100KB. En contraposición Samza es capaz de guardar el estado en un almacenamiento clave-valor por cada task.

2.3.4 Otras alternativas: PL/SQL

Otro enfoque posible, y quizás, más clásico, pero práctico para empresas con un recorrido más largo en SQL es utilizar un lenguaje procedural como Transact-SQL ( SQL Server) o PL/SQL (Oracle).

En el caso más específico de PL/SQL existen artilugios como las vistas materializadas (materialized views) que permiten tener una query cacheada que podremos refrescar a demanda. La arquitectura se mantendría intacta, aunque en este caso los agregadores (ya no tienen que estar escritos para Flink, Storm o Samza) lo que harían es lanzar un procedimiento almacenado que refresque esta vista

22 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

materializada. No obstante, y tras haber hecho pruebas con este artilugio, vimos que no hacía falta refrescar toda la vista siempre, por lo que era más simple usar una tabla de agregación y no una jerarquía de vistas materializadas.

Otra opción es hacer tablas de agregación que rellenemos a mano con un procedimiento almacenado, una opción mucho más conveniente si la lógica no es tan sencilla como reevaluar una sentencia SELECT.

En el caso de utilizar procedimientos almacenados, deberemos tener en cuenta los mismos principios de Stream Processing que se utilizan con procesadores de streaming: no debemos hacer dobles inserts, la lógica debe mantenerse centralizada.

Si nos imaginamos el flujo de datos sería algo así:

Ilustración 14. Esquema con un enfoque SQL

2.4 Herramientas de intermediación de mensajes

Como hemos visto en el capítulo Estado del Arte se discuten distintas posibilidades en la elección de herramientas de intermediación de mensajes, componentes que nos permiten separar las distintas capas de la arquitectura y mantener los distintos módulos desacoplados. En este capítulo se pretende explicar sus diferencias, similitudes y conveniencias en distintas situaciones.

2.4.1 Apache Kafka

Apache Kafka es un sistema de procesamiento en streaming distribuido, basado en la arquitectura publish/subscribe. Es la piedra angular en la arquitectura de Jey Kreps,

23 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

donde la necesidad de reprocesar elementos es un requisito, y donde reprocesar implica volver hacia atrás en un log ordenado mantenido por Apache Kafka.

Kafka está basado en logs ordenados de este estilo:

Ilustración 15. Logs ordenados en Kafka

Un topic de Kafka se constituye de varios de estos logs:

Ilustración 16. Un topic de Kafka constituido por varios logs

Cada consumidor de Kafka mantiene un offset, un puntero que le indica hasta donde ha leído y a partir de donde debe leer la siguiente vez que lo haga. En cada lectura este puntero se desplaza una vez. Los productores escriben al final de la cola, y como se espera, Kafka garantiza que se hará en orden.

24 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 17. Consumidores en Kafka con distintos offsets

Esto convierte, de facto, a Kafka en una buena herramienta de almacenamiento, que como ya veremos, muchas herramientas de procesamiento en streaming aprovecharan como característica capital de cara a implementaciones de Kappa. Esto debido a que el reprocesamiento que se necesita en la arquitectura kappa implica levantar un nuevo consumidor de Kafka y leer desde el principio del topic con la nueva lógica implementada.

Otras ventajas que nos ofrece Kafka es que ofrece replicación (por defecto, sin tener que configurar nada complejo) y tolerancia a N-1 fallos, donde N es el factor de replicación.

En cuanto a rendimiento existen comparativas con otros sistemas donde Kafka llega a escribir dos millones de registros por segundo en hardware barato. Está comprobada su escalabilidad y se utiliza en grandes empresas como Linkedin, donde llegan a escribir diez millones de registros por segundo en hardware de gama media [LIN14].

2.4.2 RabbitMQ

RabbitMQ es un broker de mensajes tradicional, multiproposito. Es ligero y de fácil despliegue tanto en servidores locales como en el cloud. Se puede ejecutar en muchos sistemas operativos, además de proveer una lista bastante amplia de conectores para distintos lenguajes.

Entre sus funcionalidades a alto nivel encontramos:

25 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

- Mensajería asíncrona: soporte a distintos protocolos, acuses de entrega, encolamiento de mensajes, enrutamiento y distintos tipos de intercambios. - Despliegue distribuido: soporte de clústers y federaciones. - Herramientas y plugins: variedad muy amplia de herramientas de integración continua, métricas operacionales, e integración con otros sistemas empresariales. Posibilidad de extender la funcionalidad mediante plugins. - Experiencia del desarrollador: posibilidad de despliegue mediante BOSH, Chef, Docker y Puppet. Soporte a la mayoría de lenguajes más populares (Java, .NET, PHP, Python, Ruby, Go, etc.) - Seguridad: Soporte de TLS y LDAP. - Administración y monitorización: Provee una interfaz para monitorizar RabbitMQ.

Aunque tiene una capa open source, la empresa propietaria de RabbitMQ, Pivotal Software ofrece una licencia comercial que expande la lista de funcionalidades antes mencionada, dándole un valor añadido a la administración de RabbitMQ.

RabbitMQ fue el primer software de código abierto que resolvía la comunicación de nodos dentro del protocolo AMQP (Advanced Messaging Queue Protocol, un protocolo de mensajería con funcionalidades potentes en cuanto al enrutamiento). A la par, existían otros sistemas de mensajería distribuida como Java JMS, pero éste no se integraba bien con otros lenguajes que no fueran Java.

A bajo nivel, su arquitectura está pensada para resolver múltiples problemas de integración, es decir, se construyó con un enfoque multipropósito: punto-a-punto, request-reply, publish-subscribe, etc. Se puede decir, que en RabbitMQ la inteligencia está en el broker, mientras que los consumidores son más básicos. Es el broker quien conoce el estado de cada consumidor. En contraposición a Kafka, donde el consumidor es inteligente, y puede reprocesar los mensajes en el broker, conoce su estado, etc.

26 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 18. Arquitectura de RabbitMQ

La comunicación en RabbitMQ puede ser síncrona o asíncrona, según las necesidades. La magia ocurre en el desacople que aportan los exchanges de RabbitMQ, evitan que se tenga que hardcodear la lógica de enrutamiento en los productores. Desde el punto de vista arquitectónico, la de RabbitMQ es una arquitectura mucho más simple que la de Kafka, que se basa en el complejo sistema de coordinación de Zookeeper. En el caso de RabbitMQ la única dependecia que nos hemos encontrado es la necesidad de instalar Erlang, ya que el broker de Rabbitmq es un hilo de erlang resolviendo la lógica.

En cuanto al almacenamiento que provee Kafka y que no está previsto en la arquitectura de RabbitMQ, se puede resolver almacenando los mensajes en una base de datos auxiliar como Cassandra o LevelDB

Algunos casos de uso rápidos que nos encontramos en la documentación de RabbitMQ incluyen:

- Comunicación punto a punto

Ilustración 19. Caso de uso punto a punto con RabbitMQ

- Work queues, balanceo de cargas

27 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 20. Balanceo de cargas con RabbitMQ

- Publish/Subscribe, donde la X es Exchange

Ilustración 21. P/S con RabbitMQ

- Enrutamiento

Ilustración 22. Routing con RabbitMQ

- Topics, o patrones

28 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 23. Topics o patrones con RabbitMQ

- RPC, con una cola de requests y otra de respuestas

Ilustración 24. RPC con RabbitMQ

Bajo el punto de vista de nuestras necesidades, el caso de uso que mejor se ajusta a lo que necesitamos es el primero, el punto a punto, con una base de datos de agregación al final del pipeline y otra que guarde el histórico

Ilustración 25. Stream processing con RabbitMQ

29 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

2.4.3 Apache DistributedLog

Apache DL es un un servicio de logs distribuidos de alto rendimiento. Ofrece durabilidad, replicación y consistencia, bases de cualquier sistemas distribuido potente. Es el sucesor de Kestrel, y también ha sido construido en el seno de Twitter.

La unidad mínima de secuencias de registros en DL, se llaman Logs o Logs Streams. Los procesos que leen se llaman readers y los que escriben, se llaman writers.

El stack de la arquitectura es algo compleja:

Ilustración 26. Stack de arquitectura de DistributedLog

Los logs, que son equivalentes a los topics de Kafka, están ordenados y son una secuencia inmutable de registros log (log records). Cada log record tiene una estructura mínima compuesta por un identificador secuencial único o distributedlog sequence number (DLSN), además cada aplicación puede asignar un identificador auxiliar o transactionid (txid). Cualquiera de estos dos parametros servirán para que los lectores sepan posicionarse dentro de un log stream.

A su vez, un log stream se divide en logs segments, que son agrupaciones de logs records de igual tamaño distribuidos en todos los nodos de la red, permitiendo un mayor escalado del sistema. Esto es una consecuencia de BookKeeper, más que una decisión de diseño de DistributedLog.

30 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Otro punto dentro de la anatomía de un log stream son los namespaces, que básicamente son una agrupación lógica de los logs.

Ilustración 27. Anatomía de un Log Stream

Volviendo al stack de la arquitectura, y teniendo en cuenta la anatomía de los log streams, los writers pueden escribir en los logs de su elección. DistributedLog asegura que los mensajes se añadirán al final del log. También se asegura que solo habrá un escritor activo en simultaneo, en caso del particionado de la red, DistributedLog asegura la tolerancia a particiones y la consistencia del dato guardado.

Al igual que Apache Kafka, en DistributedLog los readers pueden leer desde una posición relativa dentro de un log, ya sea un TXID o un DLSN. En estos escenarios, la responsabilidad de saber desde qué posición debemos leer recae en la aplicación y no en el broker (lo que significa smart consumer).

Este servicio se encontraba en incubación hasta hace muy poco tiempo, con una primera release el 27 de abril de 2017. Debido a este pequeño tiempo de vida aun no tiene grandes adopciones ni un gran soporte de los distintos lenguajes de

31 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

programación a nivel de de conectores e interfaz. Sin embargo es una alternativa a Kafka bastante interesante y que seguramente vaya a tener mucho éxito en el futuro.

2.4.4 MSMQ

Microsoft Messaging Queue es una tecnología, creada por Microsoft e integrada en su sistema operativo Windows desde la versión NT con MSMQ 1.0. Permite que dos aplicaciones se comuniquen a través de redes heterogéneas aunque alguna de las aplicaciones consumidoras no esté disponible temporalmente. La topología de ejemplo es básica:

Ilustración 28. Topología básica de MSMQ MSMQ garantiza la entrega del mensaje, enrutamiento eficiente, seguridad y mensajería basada en prioridades.

Se puede utilizar en escenario donde haga falta una respuesta síncrona, así como también en escenarios asíncronos. Microsoft declara los siguientes escenarios como casos de uso típicos:

− Misiones críticas, como servicios financieros o comercio electrónico. − Comunicación en sistemas empotrados − Workflows

Está orientado a desarrolladores de .NET, en sus dos variantes de C# o C++. Todas las herramientas de desarrollo de Microsoft soportan esta tecnología.

A bajo nivel, permite que desde una misma cola enviemos el mismo mensaje a todas las aplicaciones, y que todas sean capaces de procesarlo en paralelo (multicast). Para ello cada cola deberá depender de una cola multicast. Esta funcionalidad es incompatible con las colas transaccionales donde se pueden realizar varias

32 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

operaciones con el mismo mensaje y solo eliminarlo hasta que se hayan completado todas las subtareas.

Es importante notar que MSMQ funciona distinto según la versión de Windows del host. Como experiencia particular, MSMQ no dispone de la versión de colas multicast en Windows Server 2008 R2, pero Windows 7 si. Esta diferencia supuso una medida de contingencia en el equipo de desarrollo de GSDashboard al momento de su puesta en producción.

Se ha realizado la instalación de MSMQ en el “Anexo #2 - Instalación de MSMQ y pequeña demo”.

33 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

3. Capitulo III: Especificación de requisitos del software

3.1 Introducción

En este capitulo se trata de hacer una especificación de requisitos del software de manera formal, según el estándar IEEE-830. El software en conjunto a especificar es el GS Dashboard, objeto de estudio de este Trabajo Fin de Máster.

3.1.1 Propósito

El propósito de este capítulo es definir, a alto nivel, las funcionalidades, objetivos y características del software GS Dashboard. El público de este documento es, sobretodo, para quien vaya a tomar el testigo en su mantenimiento y/o evolución, por ejemplo un nuevo trabajador de la empresa contratado específicamente con este fin, y que no tenga mayor conocimiento del sector económico de la empresa.

3.1.2 Alcance

El software GS Dashboard está pensado como un centro de mando (un Dashboard) donde poder visualizar y resumir la información de la planificación o programación de una temporada (datos de entre 2 semanas a 12 meses).

Ilustración 29. Selector de proyectos en GS Dashboard

Cada temporada es llamada “proyecto”. Un proyecto tiene una fecha de validez, y una descripción con los datos de oferta de transporte exportada por la empresa cliente (en este caso, un operador italiano).

34 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

El beneficio de presentar una interfaz donde se identifique el estado de cada tren cada día es que permite centrarse en aquellos trenes que tengan un estado específico (por lo general, que requiere atención) en un día en concreto y actuar en consecuencia.

El centro de mando, permitirá: − Filtrar los trenes o recursos según un estado concreto − Buscar información de estados para un tren en concreto − Saber todos los gráficos donde se encuentra el tren − Gestionar la completitud de la planificación de toda la oferta comercial, es decir, saber qué falta por hacer. − Agrupar los estados por unidades de negocio más relevantes, como residencias o tipos de material rodante. − Conocer qué días requieren especial atención por parte de un operador − Monitorizar en tiempo real la planificación introducida en el software de planificación GoalRail. − Pivotar entre distintas perspectivas de la planificación

El centro de mando, no permitirá: − Corregir automáticamente errores de planificación − Planificar automáticamente los servicios o recursos presentes en la oferta comercial − Proponer una nueva planificación, ni proponer la modificación de una planificación ya existente − Optimizar una planificación − Gestionar la infraestructura u oferta comercial

3.1.3 Definiciones, siglas y abreviaciones

Algunos de los conceptos utilizados dentro de este dominio son los siguientes: − Error de planificación, ocurren cuando la planificación validada no es viable por alguna razón. Por ejemplo, intentar planificar un tren que solo circula los días laborales en un día festivo. Esto produciría un aviso en la herramienta para que el operador se centrase en ese día y tren. − Gráfico, son los documentos internos que gestiona GoalRail, pueden ser de varios tipos: días tipo (días que se van a repetir mucho a lo largo de la temporada), semana tipo (semana sin días festivos y que debería ser la más representativa de la temporada), y semanas reales que son conjuntos de 1 o más

35 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

días, que sirven para corregir aquellos días donde la planificación “tipo” no es posible. Existen además otros dos tipos de gráficos: calendarios tipo y calendarios reales. Los calendarios permiten planificar la asignación de tareas a los distintos recursos. Existen tareas que solo pueden ser asignadas en días tipo, y que posteriormente se corregirán en calendarios reales. − GoalRail, es la herramienta de planificación perteneciente a la misma empresa propietaria de GoalRail. Es un software que permite el cálculo, optimización y gestión de planificaciones para transporte interurbano (ferroviario o no). − Infraestructura, conjunto de paradas y tramos que conforman la red de transportes donde circula la oferta comercial. − Oferta comercial, conjunto de trenes ofrecidos en una temporada. − Recurso, conjunto de trabajadores a asignar tareas y trenes. Pueden ser conductores o acompañantes. − Residencia, unidad de negocio a la que pertenece un recurso. Por ejemplo, en España hablaríamos de la residencia Madrid comprendida por las estaciones Chamartín y Atocha. − Tren, viaje, elemento más atómico de la planificación. Por ejemplo: el regional 24523 que cubre la ruta Génova - Roma y sale a las 07:11 los sábados laborales. Es distinto del tren 23633 que también cubre la ruta Génova - Roma, pero sale a las 08:51 los sábados laborales.

3.1.4 Apreciación global

En este apartado se ha pretendido introducir al lector en los distintos aspectos a tener en cuenta al abordar el GS Dashboard. En apartados póstumos se profundizará en mayor detalle sobre lo que hace la herramienta, cómo interactuan los distintos módulos y cuales serán los casos de uso que se le dará a la herramienta.

36 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

3.2 Descripción global

3.2.1 Perspectiva del producto

Ilustración 30. Diagrama de bloques del sistema

El sistema se encuentra compuesto por varios módulos:

− Proxy, es el módulo que se encarga de recepcionar las llamadas externas al sistema. Encola la petición en el módulo Queue. − Queue, es el módulo que se encarga de gestionar la cola de peticiones. − Workers, es el módulo que desencola una petición y la procesa. − Web Application, es la capa de presentación de este sistema.

En este apartado se detallarán las interacciones entre todos estos módulos y sus respectivas interfaces. También se explicará como interactua con otros nodos dentro del sistema, en concreto, con el SGBD y GoalRail.

3.2.1.1 Interfaces del sistema Se proveen la siguiente interfaz:  UpdateGraph(ID_GRAPH, OP_TYPE), que sirve para encolar una petición en el sistema. Donde:  ID_GRAPH indica el gráfico de GoalRail al que se hace referencia y  OP_TYPE es la operación a realizar, pudiendo ser:  OPERATION_UPSERT, para insertar o actualizar el gráfico  OPERATION_DELETE, para eliminar el gráfico

37 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

3.2.1.2 Interfaces del software

Nombre GoalRail Código mnemotécnico GBH Versión 5.4.70+ Descripción Software de cálculo de planificaciones de transporte interurbano

Nombre Oracle Database Código mnemotécnico Oracle Versión 12c Enterprise Descripción Sistema de gestión de bases de datos

Nombre Apache Flink Código mnemotécnico Flink Versión 1.4 Descripción Procesador en streaming

Nombre Apache Kafka Código mnemotécnico Kafka Versión 1.1.0 Descripción Herramienta de intermediación de mensajes

Nombre Microsoft .NET Framework Código mnemotécnico .NET Versión 4.5+ Descripción Librerías de programación

Nombre Microsoft Message Queueing Código mnemotécnico MSMQ Versión 5.0+ Descripción Herramienta de intermediación de mensajes

Nombre Internet Information Services

38 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Código mnemotécnico IIS Versión 7.5+ Descripción Servidor de aplicaciones web de Microsoft.

3.2.1.3 Interfaces de comunicaciones Se conocen tres interfaces de comunicación: − HTTP en UpdateGraph, se trata de un endpoint de un webservice en SOAP. − TCP en Send/Receive, se trata de la comunicación utilizada por Kafka y MSMQ para funcionar. − HTTP/HTTPS, para servir el contenido web desde el IIS.

3.2.2 Funciones del producto

3.2.2.1. Casos de uso

Ilustración 31. Diagrama de casos de uso del sistema

Como se puede observar, los casos de uso serán, principalmente:  Proxy  Actualizar un gráfico, que consistirá en encolar el gráfico a procesar, para que luego un Worker se levante, lo desencole y lo procese.  Worker

39 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

 Procesar un gráfico, que después de desencolar un gráfico, almacenará y agregará la información dentro de un proyecto.  Web Application  Visualizar un proyecto, en forma de interfaz web que permitirá una navegación amigable y potente.

3.2.2.2. Diagramas de actividad

Ilustración 32. Caso de uso: Actualizar un gráfico

Ilustración 33. Procesar un gráfico

40 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 34. Visualizar proyecto

41 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 35. Obtener información agregada

Ilustración 36. Almacenar información de gráfico

42 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 37. Agregar información de proyecto

3.2.3 Características del usuario

3.2.4 Restricciones

3.2.5 Atención y dependencias

3.2.5.1. Requisitos pospuestos

3.3 Requisitos específicos

3.3.1. Requisitos de desarrollo

3.3.2. Atributos del software

43 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

4. Capitulo IV: Arquitectura heredada

Dentro de cada temporada puede verse la planificación en distintos planos (pestañas superiores): − Materiale: planificación de viajes (trenes) realizados por tipo de material rodante. − Condotta: planificación de qué conductor realiza qué viaje (tren) − Bordo: planificación de qué personal de servicio realiza qué viaje (tren), acompañantes. − Calendarización de condotta: cronograma de trabajo de conductores (días de libranza y trabajo) − Calendarización de bordo: ídem, para personal acompañante.

Ilustración 38. Distintas vistas de GS Dashboard

Dentro de cada plano podemos agrupar la información por distintos conceptos: − Tren (arriba, izquierda): viaje, elemento más atómico de la planificación. − Gráfico (arriba, derecha): documento que maneja la herramienta de planificación y agrupa una gran cantidad de trenes con algún otro concepto que mantiene la cohesión de los mismos (residencia o tipo de material). − Tipo de material (abajo, izquierda): modelo de locomotora a planificar. Por ejemplo: 245-5. − Residencia (abajo, derecha): estación a la que pertenece el personal. Por ejemplo: Madrid-Atocha

La información asociada a cada tren-viaje es el estado. Existen 8 posibles estados (botonera de colores entre la tabla y las pestañas de vistas). Cada estado es cargado

44 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

a partir de la planificación del software de optimización. Se representan con cajas de colores. Además es posible filtrar la información haciendo click sobre alguna de ellas:

Ilustración 39. Filtro de estados de GS Dashboard

Todo esto genera una gran combinatoria de datos, en la última temporada que se cargó, bajo la arquitectura clásica, se alcanzaron los 300 M de registros, aunque muchos de estos registros se debe a que el mismo tren aparece repetido en varios gráficos con distinto estado.

Si el sistema tiene, aproximadamente, 3000 trenes, y cada tren aparece en un gráfico como mínimo, para 365 días, tenemos un millón de registros; si además debemos tener la información de cada tren en 3 “ambientes”: material, conductores y bordo son tres millones de registros. En una temporada normal, se pueden llegar a crear 100 gráficos, eso permite llegar a 300 millones de registros sin mayor problema.

Ilustración 40. Arquitectura clásica de GS Dashboard

Bajo la arquitectura clásica, Antes lo que se hacía era agregar la información en cada petición del navegador, eso causaba tiempos de respuesta inadmisibles. Tanto las escrituras como las lecturas eran muy lentas.

Con la nueva arquitectura, la mejora en cuanto al volumen de datos es que se tendrán como mucho tres millones de registros estáticos por cada proyecto, donde solo se agregará el estado conforme vaya avanzando la planificación en GoalRail(r).

45 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

5. Capitulo V: Diseño de una nueva arquitectura

5.1 Requisitos

Como se ha indicado en capítulos anteriores, el principal problema de GS Dashboard reside en que no tiene una arquitectura orientada a tratar con millones de datos, y responder con tiempos de lectura aceptables. Por lo tanto se propondrá una nueva arquitectura bajo los conceptos de Stream Processing que estamos estudiando.

Para ello enumeraremos los distintos problemas a los que debe hacer frente esta nueva arquitectura: − REQ-1: Evitar condiciones de carrera en el procesamiento de los eventos. − REQ-2: Contar con la posibilidad de recuperar el estado final de los datos en caso de error. − REQ-3: Agregar los eventos con el fin de obtener distintos datos consolidados. − REQ-4: Reducir los tiempos de lectura actuales. − REQ-5: Posibilidad de consultar los datos mientras estén evolucionando. − REQ-6: Posibilidad de integrarse con herramientas de procesamiento actuales tales como Storm o Flink.

El REQ-1 se traduce en la utilización de una cola de eventos, que nos permita procesar los eventos con un orden secuencial. Las posibilidades en este punto son varias: desde opciones gratuitas como Apache Kafka o ActiveMQ, hasta otras menos conocidas como RabbitMQ, MSMQ, etc. En el capítulo correspondiente estudiaremos algunas de ellas hasta decidirnos por una.

Sobre el REQ-2, nos referimos a que debe contar con algún mecanismo que nos permita guardar un histórico de datos introducidos, y también con la posibilidad de recuperar el mismo con fines de recuperación ante fallos.

En el punto REQ-3, indicamos que esta arquitectura debe soportar N agregadores para los distintos conceptos que se han descrito en el capítulo V. Sobre GS Dashboard, tales como la agregación del estado de cada tren por cada día, la agregación de estados para un tipo de material en los distintos gráficos, etc.

46 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

El requisito REQ-4 se conseguirá como consecuencia de implementar el enfoque de agregadores del REQ-3. La aplicación web debería leer tablas con filas que no van a crecer mucho durante el ciclo de vida y que básicamente tienen el dato agregado.

Con el REQ-5 queremos poner especial importancia en que esta sistema debe funcionar en tiempo real. Esto quiere decir que mientras que los operadores estén programando las distintas referencias, pueda estar un planificador supervisor observando y analizando el avance.

Además de poder añadir agregadores propios, se quiere poder integrar GS Dashboard con otros procesadores en streaming de terceros, más sofisticados. Nos referimos al REQ-6. En los siguientes capítulos se hablará en detalle de algunas de las opciones disponibles.

Con todos estos requisitos, la nueva arquitectura debería tener una forma parecida a esta:

Ilustración 41. Propuesta de arquitectura

47 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

5.2 Elección de un procesador en streaming

Dado el recorrido que tiene la empresa propietaria de GS Dashboard, y dada la arquitectura acordada con el cliente final, la opción con una adopción mucho más ligera y llevadera es la de PL/SQL. Sin embargo, se han desarrollado ejemplos de pequeños casos de uso a modo de microservicios en la sección de ANEXOS.

Sobre las otras herramientas procesadoras en streaming, Apache Flink ha parecido ser realmente simple de aprender y desplegar, complicándose más el despliegue y la curva de aprendizaje en el resto. En el capítulo 5.. Solución con Kafka y Flink discutimos una implementación de GS Dashboard con Flink como procesador en streaming.

No obstante, esta decisión sufrió algún cambio mientras se redactaba esta documentación. Por ejemplo, se centralizó la lógica de los datos en un solo procedimiento almacenado, mientras que existe otro que consolida o agrega los datos finales en tablas de agregación.

A bajo nivel, existe un procedimiento almacenado que almacena (ALMACENAR_CENTRO_CONTROL) en la tabla GW_DASHBOARD_WAREHOUSE, la información que luego se va a agregar otro procedimiento almacenado (DBOARD_AGG_TRAIN_STATUS) y que almacenará el consolidado en distintas tablas, pivotando por diferentes columnas de GW_DASHBOARD_WAREHOUSE. La estructura de tablas es la siguiente.

Ilustración 42. Modelo de tablas utilizado

48 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

5.3 Elección de una herramienta de intermediación de mensajes

En cuanto a las herramientas de intermediación hemos repasado algunas interesantes propuestas y librerías de vanguardia.

La potencia de Kafka ha influido en otras librerías como por ejemplo DistributedLog. Su versatilidad, y la potencia de guardar un registro histórico de todo lo que ocurre hacen de Kafka la herramienta predilecta para el Stream Processing. No obstante, la complejidad añadida de tener que mantener dos sistemas: Kafka y Zookeeper son una desventaja dificil de ignorar en un proyecto piloto como GSDashboard.

En cuanto a DistributedLog, la poca adopción de un sistema nuevo implica que existe una comunidad de soporte relativamente inmadura, que compromete la estabilidad de un proyecto que va a entrar en producción. Sin embargo, DL promete mucho para el futuro y no cabe duda de que será de una de las principales herramientas dentro del ecosistema de Stream Processing.

RabbitMQ y MSMQ son alternativas con más sentido para el cliente final que va a utilizar GSDashboard por dar un amplio soporte a la plataforma Windows. Es que tan solo con una cola de MSMQ somos capaces de gestionar el tráfico de mensajes para nuestra nueva arquitectura. Quizás MSMQ no sea una solución para cualquier situación, pero en este caso disminuye considerablemente el riesgo de adoptar una tecnología inmadura como DistributedLog, o que no termina de dar el soporte adecuado en Windows como ocurre con Kafka, y sin tener que depender de terceros como ocurre con RabbitMQ.

Aunque para este proyecto que ha entrado en producción hemos utilizado MSMQ, en el capítulo 5. Solución con Kafka y Flink, discutimos una implementación del GS Dashboard con Apache Kafka como intermediador de mensajería.

49 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

5.4 Puesta en producción con MSMQ y PL/SQL

La puesta en producción de GS Dashboard fue primera semana de 2018, entre el 1 y el 7 de Enero. Fue una puesta en producción dura, como todas, pero se superó y hasta el momento de redacción de este documento el cliente está satisfecho y no se ha vuelto a quejar de los mismos problemas de lentitud que empujaron a la desconexión en 2017. El éxito de esta puesta en producción ha sido gracias al cambio de arquitectura que certeramente se produjo para este producto.

Recordemos los requisitos que habíamos listado para esta arquitectura: − REQ-1: Evitar condiciones de carrera en el procesamiento de los eventos. − REQ-2: Contar con la posibilidad de recuperar el estado final de los datos en caso de error. − REQ-3: Agregar los eventos con el fin de obtener distintos datos consolidados. − REQ-4: Reducir los tiempos de lectura actuales. − REQ-5: Posibilidad de consultar los datos mientras estén evolucionando. − REQ-6: Posibilidad de integrarse con herramientas de procesamiento actuales tales como Storm o Flink.

De todos ellos, el que más valor le aporta al cliente, es el REQ-4, ya que los tiempos de lectura se traducen en tiempo de espera al cargar la interfaz web. Esto se resuelve gracias a que la aplicación web dejará de agregar todos los datos en tiempo de la HTTP Request, y simplemente leerá el consolidado en las tablas de agregación.

Ilustración 43. Arquitectura de GS Dashboard

REQ-2 aunque se resuelve fácilmente con Apache Kafka o Apache DistributedLog, se puede conseguir también con la arquitectura actual. De hecho en tiempo de depuración y pruebas, se resconstruyó el estado mediante el reprocesamiento de todo el log. Esto es particularmente útil cuando hay que tratar situaciones

50 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

excepcionales en los datos, donde algo deja de ser relevante para el cálculo del dato agregado.

REQ-1 se consigue al bloquear la escritura en tablas sobre las que vamos trabajando. Teóricamente es posible trabajar con más workers distribuidos con esta arquitectura sin ningún tipo de problemas. Utilizando otras arquitecturas en las que está Apache Kafka quizas es mucho más fácil ya que es esta herramienta la que se encarga de gestionar el consenso por debajo.

REQ-3 fue satisfecho con el procedimiento DBOARD_AGG_TRAIN_STATUS que se encarga de agregar el mismo conjunto de datos pivotando en distintas columnas del mismo. Existe una tabla por cada dato agregado.

REQ-5 es una propiedad intrínseca de Stream Processing. Aunque tengamos 10 trabajos en cola, podremos ver la evolución de los datos mientras estos trabajos van completándose.

REQ-6 es factible gracias a MSMQ, podríamos tener otro worker escuchando la misma cola que se encargase de replicar los datos en topics de Apache Kafka. Por ejemplo, en el ANEXO 2 se hizo una demostración de este requisito al trasladar datos de una cola de MSMQ a un topic de Kafka.

51 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

5.5 Solución con Kafka y Flink

La arquitectura que fue puesta en producción puede, no obstante, ser implementada en tecnologías distintas y más sofisticadas que PL/SQL y MSMQ. En este capítulo se propone la implementación de esta arquitectura basada en Stream Processing con Apache Kafka y Apache Flink.

Ilustración 44. Solución con Kafka y Flink

El diagrama con el que se representa esta implementación difiere de lo que se propuso en el apartado anterior, sin embargo, es una arquitectura mucho más escalable, aprovechándose de las ventajas de estar construido sobre Kafka. La entrada y la salida de nuestro sistemas se mantiene intacta, con lo cual el frontend no tendremos que adaptarlo.

Ilustración 45. Diagrama de flujo de nuestro programa en Flink

52 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

En el diagrama de la Ilustración 37, se recorren rápidamente todos los pasos que se han escrito para el agregador en Flink. A continuación, una pequeña descripción por cada uno de ellos:

1. Source(), en este paso se indica el origen de los datos, que no es ni más ni menos que un topic de Kafka que se ha de indicar en los argumentos de entrada. 2. Map(), es la función con la que se mapean (como su nombre indica) los datos de entrada en JSON a objetos tupla de Kafka. En nuestro caso, cada objeto JSON se mapea en un Tuple14<> con los distintos campos que se espera. Mapear la entrada a tuplas, nos facilita transformaciones posteriores. La razón de haber utilizado el objeto Tuple14 de Flink es porque las tuplas que utilizamos siguen el mismo modelo de datos que discutimos en 2.E. Elección. 3. KeyBy(), en este punto se agrupan los datos por lo que en nuestro de modelo de datos es la Primary Key (project, id_resource_type, id_calc_type, item_name, day). 4. Window(), así le indicamos la cantidad de datos que debe recuperar de cara a la agregación del punto siguiente. En este caso nos interesa que sea una ventana global, aunque también puede interesarnos en otros casos de uso, quedarnos con los últimos elementos y con todos los elementos en los últimos minutos. 5. Trigger(), modela la frecuencia con la que debe lanzarse la siguiente operación de transformación. En este caso nos interesa que se lance cada vez que se recoge un elemento. 6. Aggregate(), esta es la función que agrega los datos recolectados por KeyBy() y Window() y se queda con un agregado de ellos. En este caso hemos definido que la función de agregación devuelve el mayor estado asociado a los datos de la Key. 7. Sink(), es el sumidero donde se ha de dejar los datos de salida. En este caso es un KafkaProducer.

Con esta implementación se cumplen los mismo requisitos planteados, incluso se consigue una mejor escalabilidad gracias a la facilidad de escalar de Kafka y a la posibilidad de clúster de Flink.

53 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 46. Pruebas de la implementación en Flink

Se han hecho pruebas de verificación sobre esta implementación. Nuestra aplicación en Flink es fácilmente depurable desde Eclipse. Haciendo el seguimiento del código se puede ver que los eventos que son compatibles (es decir, se ha verificado que la operación KeyBy agrupa correctamente los eventos).

Una prueba simple es enviar un evento con un producer de console de Kafka, y a continuación enviar el mismo evento con el dato de ID_STATUS cambiado. La salida debe mostrar la actualización del estado de forma coherente, como muestra la Ilustración 38.

54 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

6. Capitulo VI: Pruebas

6.1 Pruebas de rendimiento

Se trata de hacer pruebas donde se certifique la mejora en términos de rendimiento conseguida con el nuevo paradigma, en comparación con el paradigma anterior o clásico.

La diferencia en tiempos de lectura es abismal entre los dos paradigmas. A continuación mostramos algunas medidas tomadas con la versión anterior y actual de GSDashboard.

Escenario de lectura Paradigma clásico Paradigma Stream Processing Carga inicial (Vista DT) 5.35s 1.27s Refresco con un filtro 15.30s 0.53s Selección manual (7 días) 9.12s 2.37s Selección manual (30 67.20s 10.30s días) Vista escenarios (ST) 35.40s 0.47s Vista escenarios (SM-7) 37.25s 0.54s Vista escenarios (SM-30) 84.15s 6.27s

Claramente se ha ganado en rendimiento con el nuevo paradigma en cuanto a tiempo de lectura. Los escenarios que se indican en la tabla superior no son todos, pero son los más representativos de cara a el flujo operativo de un usuario normal.

Esta prueba se ha realizado con el mismo ordenador y contra el mismo servidor para que los resultados sean comparables.

55 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

7. Capitulo VII: Conclusiones

Brevemente, se recuerda cuales fueron los objetivos de este documento:

− Estudiar el estado del arte en Stream Processing − Diseñar una nueva arquitectura para GS Dashboard con los conocimientos adquiridos de Stream Processing. − Desarrollar e integrar los componentes dentro de la nueva arquitectura distribuida. − Adecuar el módulo web de GS Dashboard − Realizar comparativas de rendimiento con una y otra arquitectura. − Estudiar software de terceros (y actuales) dentro del mundo de Stream Processing.

Con lo cual, se puede concluir este brevísimo monográfico sobre Stream Processing en lo siguiente:

Stream Processing no es una novedad, desde hace muchos años se habla de ella en libros y se estudia a diferentes niveles y distinta profundidad. No obstante, lo que si que es una novedad es la gran cantidad de alternativas en cuanto a implementación que nos facilita llevarla al día a día en organizaciones de distinto tamaño.

Al vivir en la época de la cuarta revolución industrial, donde todo gira al rededor de la disponibilidad de los datos que van y podrán ser analizados, el paradigma stream processing será una pieza clave en esta nueva ola de innovación en la industria, por sus cualidades de trabajo en tiempo real y gran capacidad de procesamiento de datos con un hardware relativamente barato en comparación con otras formas de procesamiento de datos.

A tal respecto, se presentó el caso de uso de un centro de mando para una empresa del sector ferroviario, donde la primera implementación fue fallida y sin embargo se logró volver a poner en producción siguiendo la filosofía del Stream Processing. Este ejemplo puede ser utilizado para animar al lector a considerar Stream Processing como solución eficaz a problemas de rendimiento en aplicaciones web.

Stream Processing no es un paradigma de implementación cerrada, y como casi todo en la Ingeniería del Software, tiene distintas formas de ser implementado. En este

56 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

monográfico se ha abordado dos formas diferentes: una con PL/SQL y otra con Apache Flink y Apache Kafka. Cumpliéndose el objetivo de estudiar software de terceros especializados en stream processing.

El haber implementado el backend del centro de mando de formas distintas no afecta al funcionamiento del frontend, ya que el modelo de datos no ha variado. En cualquier caso las mejoras que se presentan en el capítulo VII. Comparativa de rendimiento son válidas para ambos casos porque se presentan tiempos de lectura.

En definitiva, cualquier ingeniero de software debería conocer Stream Processing, al menos a nivel teórico, ya que puede significar un cambio de paradigma que resuelva alguno de sus problemas del día a día.

57 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Referencias

[1]. Apache DistributedLog. (2017). Apache DistributedLog. Obtenido de Apache DistributedLog: http://bookkeeper.apache.org/distributedlog/ [2]. Apache Software Foundation. (2017). Obtenido de Apache Kafka: https://kafka.apache.org/ [3]. Apache Software Foundation. (2017). Obtenido de Apache Flink: https://flink.apache.org/ [4]. García Egea, T. (Agosto de 2017). Obtenido de El Pais: https://retina.elpais.com/retina/2017/10/09/tendencias/1507530622_383656.html [5]. Hausenblas, M., & Bijnens, N. (2017). Obtenido de The Lambda Architecture: http://lambda-architecture.net/ [6]. Hueske, F. (2017). Stream Processing with Apache Flink. O'Reilly. [7]. Humphrey, P. (04 de 2017). Understanding when to use RabbitMQ or Apache Kafka. Obtenido de Pivotal Software: https://content.pivotal.io/rabbitmq/understanding-when-to-use-rabbitmq-or-apach e-kafka [8]. Kleppmann, M. (2016). Making sense of Stream Processing. O'Reilly. [9]. Kreps, J. (2013). Obtenido de Linkedin: https://engineering.linkedin.com/distributed-systems/log-what-every-software-en gineer-should-know-about-real-time-datas-unifying [10]. Kreps, J. (Abril de 2014). Linkedin. Obtenido de https://engineering.linkedin.com/kafka/benchmarking-apache-kafka-2-million-writ es-second-three-cheap-machines [11]. Kreps, J. (Julio de 2014). O Reilly. Obtenido de https://www.oreilly.com/ideas/questioning-the-lambda-architecture [12]. Melo, F. (01 de 2017). Messaging patterns for event driven microservices. Obtenido de Pivotal Software: https://content.pivotal.io/blog/messaging-patterns-for-event-driven-microservices [13]. RabbitMQ. (01 de 2018). RabbitMQ. Obtenido de RabbitMQ: https://www.rabbitmq.com

58 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

ANEXOS

1. Instalación de Apache Flink y pequeña demo con Apache Kafka

Dentro de la arquitectura de GSDashboard vamos a implementar un pequeño módulo de notificaciones con Apache Flink y Apache Kafka

Aunque GS Dashboard esté escrito en .NET y CSharp, el utilizar Kafka como intermediador de mensajes nos permite inteorperar con otros módulos escritos en Java.

Paso 1. Empecemos describiendo como se instala Apache Flink. Desde la página de descargas en el sitio web de Flink encontramos los ficheros sin el bundle de Hadoop. Hemos descargado la versión 1.4.0. Es importante recordar este número porque luego tendremos que alinear las dependencias. En cuanto a Scala, usaremos la versión 2.11.

Tras la descarga, dentro de la carpeta /bin encontramos el ejecutable start-local.bat. Si ejecutamos dicho fichero habremos arrancado la interfaz web que podemos visitar en http://localhost:8081. Desde esta interfaz podremos monitorizar los scripts que hayamos programado y ejecutado.

Ilustración 47. Interfaz web de Apache Flink

59 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Paso 2. Creando el proyecto en Eclipse Como IDE de desarrollo en Java, hemos elegido Eclipse, aunque en otros IDEs pueden variar los pasos a seguir, debería ser similar en lineas generales. Utilizando la versión Eclipse Oxygen para Java EE de Diciembre de 2017, solo tendremos que: − Hacer clic en Archivo > Nuevo proyecto > Nuevo proyecto de Maven − Seleccionar el arquetipo de proyecto flink-quickstart o añadirlo si no lo hemos hecho antes. − Asignarle los nombre de artefacto y grupo requeridos para el proyecto Maven.

Paso 3. Escribiendo la lógica del filtro Si tomamos el ejemplo con el conector de Apache Kafka, tendremos un código base bastante simple y organizado a partir de donde podemos empezar a construir nuestro filtro.

Ilustración 48. Pequeño módulo de demo para notificaciones en GS Dasboard

Lo que tendremos como entrada de nuestro filtro será un stream con el conector de Kafka, de un topic en específico, gsdboard-event. En este topic nos vendrán todos los eventos que vayan ocurriendo. Solo nos interesa notificar de ciertos eventos que definiremos en la lógica.

Los eventos que vengan en la cola de entrada será un json con la información del gráfico, la operación que se va a realizar y el nuevo estado que va a tomar el gráfico en el dashboard. Si el estado es un error, el filtro lo detectará y encolará el mensaje en el sumidero de salida, que también será un stream con el conector de Kafka apuntando al topic gsdboard-notif.

El código final es el siguiente: public class NotificationsFilter {

public static void main(String[] args) throws Exception { // parse input arguments final ParameterTool parameterTool = ParameterTool.fromArgs(args);

60 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

if (parameterTool.getNumberOfParameters() < 5) { System.out.println("Missing parameters!\n" + "Usage: Kafka --input-topic --output-topic " + "--bootstrap.servers " + "--zookeeper.connect --group.id "); return; }

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.getConfig().disableSysoutLogging(); env.getConfig().setRestartStrategy(RestartStrategies.fixedDelayRestart(4, 10000)); env.enableCheckpointing(5000); env.getConfig().setGlobalJobParameters(parameterTool); env.getConfig().setGlobalJobParameters(parameterTool);

DataStream input = env .addSource(new FlinkKafkaConsumer010<>( parameterTool.getRequired("input-topic"), new SimpleStringSchema(), parameterTool.getProperties())) .filter(new FilteringFunction());

input.addSink( new FlinkKafkaProducer010<>( parameterTool.getRequired("output-topic"), new SimpleStringSchema(), parameterTool.getProperties()));

env.execute("GS Dashboard Notificacions Filter"); }

private static class FilteringFunction implements FilterFunction {

@Override public boolean filter(String arg0) throws Exception { return arg0.contains("300"); }

} }

Como podemos ver, en muy pocas lineas podemos conseguir la lógica que hemos resumido arriba. Flink nos provee abstracciones que nos permiten acelerar la productividad. En este caso podemos encontrar en las lineas inferiores dónde se realiza la conexión a Kafka. Como se puede leer en el código, el topic de entrada viene a través de los argumentos del programa.

DataStream input = env .addSource(new FlinkKafkaConsumer010<>( parameterTool.getRequired("input-topic"), new SimpleStringSchema(), parameterTool.getProperties())) .filter(new FilteringFunction());

Es en la misma instrucción donde le indicamos que debe hacer un filtrado del input con nuestra propia función FilteringFunction() que hemos definido en las líneas a continuación:

private static class FilteringFunction implements FilterFunction {

@Override public boolean filter(String arg0) throws Exception {

61 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

return arg0.contains("300"); }

}

La lógica es simple, si el registro que viene de la cola contiene el estado 300, lo identificaremos y “dejaremos pasar” como una notificación a la cola sumidero. Indicarle el sumidero a Flink es sencillo y análogo a la forma en que hemos indicado el source: input.addSink( new FlinkKafkaProducer010<>( parameterTool.getRequired("output-topic"), new SimpleStringSchema(), parameterTool.getProperties()));

En este caso, el topic de salida también nos viene indicado en los argumentos de entrada del pequeño programa que hemos escrito.

Paso 4. Levantando Apache Kafka para poder probar nuestro filtro Descargarnos Kafka es sencillo, desde la web de descargas de Kafka nos descargamos la última versión. Dentro de la carpeta /bin/windows nos encontramos todos los ejecutables necesarios. − Levantamos primero Zookeeper con el comando zookeeper-server-start.bat ../../config/zookeeper.properties

− Levantamos el servidor de Apache Kafka kafka-server-start.bat ../../config/server.properties

− Levantamos un consumidor para gsdboard-notif y otro para gsdboard-event kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic gsdboard-notif kafka-console-consumer.bat --bootstrap-server localhost:9092 --topic gsdboard-event

Paso 5. Compilando y desplegando nuestro filtro Para poder desplegar nuestro filtro deberemos compilar nuestro filtro indicando los flags package install en maven. Nos generará un fichero jar que podremos desplegar a través de la línea de comandos. El siguiente paso es ejecutar la utilidad de linea de comandos de flink apuntando a nuestro jar, e indicándole los parametros de entrada que esperamos:

62 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

flink.bat run com.goalsystems.gsdashboard.NotificationsFilter-0.0.1-SNAPSHOT.jar --input-topic gsdboard-event --output-topic gsdboard-notif --bootstrap.servers localhost:9092 --zookeeper.connect localhost:2181 --group.id 1

Si todo ha ido bien, deberíamos ver nuestra aplicación registrada en la pestaña de Running jobs en la interfaz web de Flink, de la siguiente manera:

Ilustración 49. Filtro en ejecución en Flink

Paso 6. Probando el nuevo componente En el paso 4 levantamos dos consumidores que estuviesen apuntando a la cola de salida de Kafka, el topic gsdboard-notif; y otro a la cola de entrada, gsdboard-event. Lo que haremos ahora es enviar mensajes por la cola de entrada desde el backend de GSDashboard, metiendo registros de prueba que cumplan y que no cumplan el filtro que hemos configurado (el estado debe contener 300).

Ilustración 50. Ventanas con cola de entrada y salida de Kafka tras filtro de Flink

De los cuatro registros de prueba que hemos enviado, solo se ha recibido uno en la cola de salida gsdboard-notif. Podemos concluir que el filtro ha hecho el filtro esperado.

En posteriores iteraciones de este ejercicio se debe conseguir llevar el resultado a una base de datos consolidado para que GS Dashboard pueda hacer el ejercicio de leer solo datos consolidados. Este ejercicio no entraña ninguna dificultad, es un ejemplo muy simple de lo que puede conseguirse con Apache Flink y las dificultades que un usuario novato en Apache Flink puede encontrarse en la toma de contacto.

63 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

64 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

2. Instalación de MSMQ y pequeña demo

Prerequisitos

− Utilizar un sistema operativo Microsoft Windows

Instalación

1. Inicio > Panel de control 2. Seleccionar “Programas”

Ilustración 51. Panel de control de Windows 10 3. Activar o desactivar características de Windows

Ilustración 52. Sección Programas y características de Windows 10 4. Activar todas las casillas dentro de Microsoft Message Queue (MSMQ) Server

65 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 53. Activar o desactivar las características de Windows 10 5. Reiniciar el ordenador

Se puede instalar MSMQ desde la linea de comandos, con el siguiente script en batch:

DISM /online /enable-feature /featurename:MSMQ-Container DISM /online /enable-feature /featurename:MSMQ-Server DISM /online /enable-feature /featurename:MSMQ-Triggers DISM /online /enable-feature /featurename:MSMQ-ADIntegration DISM /online /enable-feature /featurename:MSMQ-HTTP DISM /online /enable-feature /featurename:MSMQ-Multicast DISM /online /enable-feature /featurename:MSMQ-DCOMProxy

Una pequeña demo en MSMQ

De lo que se trata es de comunicar dos procesos a través de una cola MSMQ. El ejemplo más simple es ir encolando en una cola privada y desencolarlos desde el otro. En este ejemplo, nos plantearemos un proceso que encola en una cola de MSMQ, y otro que desencola el mensaje y lo “traduce” a un topic de Apache Kafka. Este componente puede ser muy útil dentro de la arquitectura que se ha diseñado

66 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

para GS Dashboard en capitulos anteriores, permitiría integrar la arquitectura con herramientas mucho más potentes como Apache Flink, o Samza.

Lo primero es crear la cola de MSMQ. Para ello tan solo hará falta un par de lineas en C#, indicando la ruta de la cola.

if (!MessageQueue.Exists(QUEUE_ADDRESS)) MessageQueue.Create(QUEUE_ADDRESS);

MessageQueue messageQueue = new MessageQueue(QUEUE_ADDRESS);

La variable QUEUE_ADDRESS representa una ruta válida de una cola de MSMQ, en nuestro caso utilizaremos: protected static string QUEUE_ADDRESS = @".\Private$\NotificationsQueue";

Posteriormente, para enviar el mensaje utilizaremos el comando Send(object). En nuestro caso, comunicaremos un objeto Scenario, que previamente hemos definido en el contrato de datos, y que .NET es capaz de serializar gracias a XML. El código, otra vez, es muy sencillo:

Scenario grafico = new Scenario(); grafico.Id = Convert.ToInt32(args[0]); messageQueue.Send(grafico.Id, "Update by scenario ID = " + grafico.Id);

Para depurar este programa, hemos generado una interfaz gráfico sencilla que nos permite enviar todos los mensajes que queramos. Podemos ver los mensajes encolados en las Herramientas Administrativas de Windows, Configuración de equipos.

67 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Ilustración 54. Lista de mensajes de MSMQ

Lo que queda es el segundo proceso, que deberá encargarse de desencolar los mensajes de MSMQ y posteriormente enviarlo a un topic de Apache Kafka. La idea es poder integrar la arquitectura al ejemplo del Anexo #1.

En el ejemplo del Anexo #1 se tomaban los mensajes desde el topic “gsdashboard-events”. En este caso, hará falta tener configurado el conector de Kafka para .NET. Primero veamos como recibimos mensajes de MSMQ.

System.Messaging.Message message = this.messageQueue.Receive(); int escenario = Convert.ToInt32(message.Body);

Previamente tendremos que haber establecido la conexión con la cola de MSMQ con las mismas líneas de código que en el ejemplo de envío de mensajes.

Ilustración 55. Mensaje de MSMQ recibido

68 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

La integración con Apache Kafka, no siendo compleja, si que obliga a escribir algunas líneas más de código para configurar el servidor, los topics, etc. Para integrar la arquitectura con Apache Kafka es necesario descargar el paquete de Nuget de un tercero que facilita esta tarea. A continuación, el comando a ejecutar en la consola de Nuget:

Install-Package Confluent.Kafka -ProjectName GSDashboard.Notificaciones

Lo siguiente es configurar el Productor de Kafka a nivel programático. En el bloque de código a continuación se le indica a Kafka a qué servidor conectarse, y sobre qué tópic operar. var config = new Dictionary { { "bootstrap.servers", ConfigurationManager.AppSettings["KAFKA_IP_PORT"].ToString() }, { "client.id", Dns.GetHostName() }, { "default.topic.config", new Dictionary { { TOPIC_EVENT, "all" } } } }; this.kafkaProducer = new Producer(config, null, new StringSerializer(Encoding.UTF8));

En nuestro caso, estas variables serán:

... protected string TOPIC_EVENT = "gsdboard-event";

Finalmente, para enviar el mensaje se utilizará la línea de código: kafkaProducer.ProduceAsync(TOPIC_EVENT, null, Encoding.UTF8.GetString(json, 0, json.Length));

Ilustración 56. Mensajes consumidos en el topic de Kafka

Con este pequeño tutorial se ha conseguido integrar en la arquitectura Kafka, lo cual a su vez, nos permite integrarnos con otras herramientas mucho más potentes.

69 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

3. Revisiones en SVN

Revision: 187989 Author: dgarcia Date: viernes, 26 de enero de 2018 12:09:45 Message: INT M25431: SNCB - Bienvenido al Centro de Control! ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs/GSDashboard/v14/.suo Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_SNCB.pubxml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_SNCB.pubxml.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_TRENORD.pubxml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_TRENORD.pubxml.us er Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Release_SNCB.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Release_TGV.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Helpers/GSDashboard.Helpers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/GSDashboard.IWorkers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/GSDashboard.Models.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_SNC B.pubxml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_SNC B.pubxml.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.Release_SNCB.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.Release_TGV.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/GSDashboard.Queries.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/GSDashboard.Repositories.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GSDashboard.WorkersService.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.sln

Revision: 187915 Author: dgarcia Date: jueves, 25 de enero de 2018 16:11:39 Message: INT M25322: TRENORD - Añado la información del idioma para cada cliente ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs/GSDashboard/v14/.suo Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Scripts.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Release.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Release_TGV.config

Revision: 187811 Author: dgarcia Date: miércoles, 24 de enero de 2018 18:26:24 Message: INT M25322: TRENORD - Metemos el flujo 1.5 en el dashboard ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Content/GSDashboard/css/gsdashboard-styles.css Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Content/GoalSystems/img/ajax-loader.gif Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj.user Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_TGV.pubxml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Scripts.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj.user Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_TRE NORD.pubxml Modified : /GoalWebSharedFolders/GSDashboard/DB/ALMACENAR_CENTRO_MANDO.prc Added : /GoalWebSharedFolders/GSDashboard/DB/TRENORD/GRM_TRENORD.V_DBOARD_UNROLL_PROJECT_MATS.vw Added : /GoalWebSharedFolders/GSDashboard/DB/TRENORD/GRM_TRENORD.V_DBOARD_UNROLL_PROJECT_TRAINS.vw Added : /GoalWebSharedFolders/GSDashboard/DB/V_DBOARD_UNROLL_PROJECT_MATS.vw Added : /GoalWebSharedFolders/GSDashboard/DB/V_DBOARD_UNROLL_PROJECT_TRAINS.vw

Revision: 187678 Author: dgarcia Date: martes, 23 de enero de 2018 16:23:48 Message:

70 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

INT T0: Subidas pendientes ---- Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Helpers/UpdateDashboardServiceHelper.cs

Revision: 187671 Author: dgarcia Date: martes, 23 de enero de 2018 15:59:03 Message: INT T0: Bienvenido TGV. Perfil de configuración ---- Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.Oficial.config Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.Release_TGV.config

Revision: 187667 Author: jordonez Date: martes, 23 de enero de 2018 15:50:34 Message: INT T0: cambiamos IP por localhost ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj

Revision: 187659 Author: dgarcia Date: martes, 23 de enero de 2018 15:22:32 Message: INT T0: Corrijo la BBDD de TGV en Oracle03 ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Release_TGV.config

Revision: 187649 Author: dgarcia Date: martes, 23 de enero de 2018 14:47:38 Message: INT T0: INT T0: Gestión multicliente para TRENORD / TGV - Cambio de nombre el perfil de publicación para TRENORD

---- Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_bcanadas.pubxml Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_bcanadas.pubxml.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_TGV.pubxml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_TGV.pubxml.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_TRENORD.pubxml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_TRENORD.pubxml.user Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_bcanadas.pubxml Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_bcanadas.pubxml.user

Revision: 187648 Author: dgarcia Date: martes, 23 de enero de 2018 14:44:39 Message: INT T0: Subidas pendientes ---- Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs/GSDashboard Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs/GSDashboard/v14 Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs/GSDashboard/v14/.suo Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs/config Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/.vs/config/applicationhost.config

Revision: 187647 Author: dgarcia Date: martes, 23 de enero de 2018 14:42:33 Message: INT T0: Gestión multicliente para TRENORD / TGV - Añado perfiles de publicaciones para el PROXY y WEB ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_TGV.pubxml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_TGV.pubxml.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Release_TGV.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Helpers/GSDashboard.Helpers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/GSDashboard.IWorkers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/GSDashboard.Models.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/App_Data Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles

71 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_bcan adas.pubxml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/PublishProfiles/GSDashboardProxy_bcan adas.pubxml.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Service References Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/GSDashboard.Queries.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/GSDashboard.Repositories.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GSDashboard.WorkersService.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.sln

Revision: 187641 Author: dgarcia Date: martes, 23 de enero de 2018 14:07:42 Message: INT T0: Gestión multicliente para TRENORD / TGV ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/App_Start/RouteConfig.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/Home/HomeViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_bcanadas.pubxml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_versionOficial.pubxml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Scripts.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Release.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/UpdateDashboardService.svc.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/App.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateMaterialTypeStatusWorke r.cs Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateResidenceStatusWorker.c s Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateScenarioStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateTrainStatusWorker.cs Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/DeleteScenarioAngReAggregateWo rker.cs Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/StoreScenarioDataWorker.cs

Revision: 187203 Author: dgarcia Date: miércoles, 17 de enero de 2018 12:36:15 Message: INT T0: Me he vuelto a confundir con los flags ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs

Revision: 187195 Author: dgarcia Date: miércoles, 17 de enero de 2018 11:47:43 Message: INT T0: TRENORD - Gestión de colas monohilo ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Oficial.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/AbstractWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/GSDashboard.IWorkers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/UpdateDashboardWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/UpdateDashboardService.svc.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate MaterialTypeStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ResidenceStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ScenarioStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/DeleteSce narioAngReAggregateWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/StoreScen arioDataWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/App.config

72 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GSDashboard.WorkersService.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GSDashboard.WorkersService.csproj.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GSDashboard.WorkersService_ClaveTem poral.pfx Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GoalCentroControlService.Designer.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GoalCentroControlService.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/GoalCentroControlService.resx Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/Program.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/ProjectInstaller.Designer.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/ProjectInstaller.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/ProjectInstaller.resx Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/Properties Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.WorkersService/Properties/AssemblyInfo.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.sln

Revision: 187092 Author: dgarcia Date: lunes, 15 de enero de 2018 15:27:44 Message: INT: Subimos versión a 0.1.0.187097 ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.config

Revision: 187090 Author: dgarcia Date: lunes, 15 de enero de 2018 15:26:32 Message: INT T0: últimas revisiones ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/TooltipController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs

Revision: 187044 Author: dgarcia Date: lunes, 15 de enero de 2018 10:23:55 Message: INT T0: TRENORD - Gestión de errores - inicialización de parametros de error ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/Commons/NotificarGoalRail.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs

Revision: 186872 Author: dgarcia Date: jueves, 11 de enero de 2018 13:41:04 Message: INT M24105: TRENORD - Estabilización del worker ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/Commons/NotificarGoalRail.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateMaterialTypeStatusWorke r.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateResidenceStatusWorker.c s Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateScenarioStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/AggregateTrainStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/DeleteScenarioAngReAggregateWo rker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/StoreScenarioDataWorker.cs

Revision: 186871 Author: dgarcia Date: jueves, 11 de enero de 2018 13:40:24 Message: INT M24105: TRENORD - Estabilización del tooltip ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/Home/SummaryTableViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/HistoricDataQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/HistoricDataRepository.cs

Revision: 186624 Author: dgarcia Date: lunes, 08 de enero de 2018 13:08:58 Message: INT M15977: Ocultamos el enlace a la vista macro

73 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/Index.cshtml

Revision: 186621 Author: dgarcia Date: lunes, 08 de enero de 2018 13:01:11 Message: INT M15977: Si no has iniciado sesión debes ir a /Login/Index no a /Account/Login ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/App_Start/Startup.Auth.cs

Revision: 186586 Author: dgarcia Date: viernes, 05 de enero de 2018 14:03:09 Message: INT M15977: TRENORD - USABILIDAD - Ahora la web indica cuantos trabajos en cola hay ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Content/GSDashboard/css/gsdashboard-styles.css Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/QueueController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/DependencyResolution/DefaultRegistry.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/Home/SummaryTableViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Scripts.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Queue Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/_GSDashboardMenuBarPartial.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/AbstractWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/UpdateDashboardWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/UpdateDashboardServiceOperation.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/GSDashboard.Queries.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/QueueQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/GSDashboard.Repositories.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/IQueueRepository.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/QueueRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/Commons Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/Commons/NotificarGoalRail.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate MaterialTypeStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ResidenceStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ScenarioStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/DeleteSce narioAngReAggregateWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/StoreScen arioDataWorker.cs Modified : /GoalWebSharedFolders/GSDashboard/dictionary/DictionaryGeneral.xml

Revision: 186536 Author: dgarcia Date: jueves, 04 de enero de 2018 13:20:57 Message: INT M15977: TRENORD - USABILIDAD - Mejoras en el diseño responsive, hago que el texto se redimensione con la resolución. ---- Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Content/GSDashboard Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Content/GSDashboard/css Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Content/GSDashboard/css/gsdashboard-styles.css Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/SharedComponents/_SelectorEstados.csht ml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/_GSDashboardLayout.cshtml

Revision: 186527 Author: dgarcia Date: jueves, 04 de enero de 2018 10:57:08 Message: INT M15977: TRENORD - Trabajo en la tolerancia a fallos, no deben perderse mensajes en caso se caiga el worker.

---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/AbstractWorker.cs

74 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/UpdateDashboardWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/HistoricDataQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/HistoricDataRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Database/DBManager.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate MaterialTypeStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ResidenceStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ScenarioStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/DeleteSce narioAngReAggregateWorker.cs Modified : /GoalWebSharedFolders/GSDashboard/dictionary/DictionaryGeneral.xml

Revision: 186526 Author: dgarcia Date: jueves, 04 de enero de 2018 10:52:52 Message: INT M15977: TRENORD - Cuando se le da al enter, es como hacer click en el botón de buscar ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Buscador.cshtml

Revision: 186310 Author: dgarcia Date: miércoles, 27 de diciembre de 2017 23:27:56 Message: INT M24102: TRENORD - La conexión con el proxy se había roto al añadir el tipo de operación en la comunicación. ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_bcanadas.pubxml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/UpdateDashboardWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/IUpdateDashboardService.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/UpdateDashboardService.svc.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.config Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/packages.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj

Revision: 186308 Author: dgarcia Date: miércoles, 27 de diciembre de 2017 20:41:25 Message: INT M24102: TRENORD - El Worker debe leer con un formatter de la cola de MSMQ, añado el worker de despublicación. ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/App.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/DeleteSce narioAngReAggregateWorker.cs

Revision: 186263 Author: dgarcia Date: miércoles, 27 de diciembre de 2017 11:09:46 Message: INT M24102: TRENORD - Despublicación de gráficos (cambios de nivel de un gráfico ya publicado). Implica cambios en el webservice con el que se integra el CC a GoalRail. ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Helpers/GSDashboard.Helpers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/GSDashboard.IWorkers.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/UpdateDashboardWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/GSDashboard.Models.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/Scenario.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/TooltipInfo.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/UpdateDashboardServiceOperation.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/IUpdateDashboardService.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/UpdateDashboardService.svc.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/HistoricDataQueries.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/ScenarioQueries.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/HistoricDataRepository.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/IHistoricDataRepository.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/IScenariosRepository.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/ScenariosRepository.cs

75 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/app.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate MaterialTypeStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ResidenceStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ScenarioStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/StoreScen arioDataWorker.cs Modified : /GoalWebSharedFolders/GSDashboard/DB/TRENORD/GRM_TRENORD.ALMACENAR_CENTRO_MANDO.prc Modified : /GoalWebSharedFolders/GSDashboard/DB/TRENORD/GRM_TRENORD.DBOARD_AGG_MAT_TYPE_STATUS.prc Modified : /GoalWebSharedFolders/GSDashboard/DB/TRENORD/GRM_TRENORD.DBOARD_AGG_RESIDENCE_STATUS.prc Modified : /GoalWebSharedFolders/GSDashboard/DB/TRENORD/GRM_TRENORD.DBOARD_AGG_SCENARIO_STATUS.prc Modified : /GoalWebSharedFolders/GSDashboard/DB/TRENORD/GRM_TRENORD.DBOARD_AGG_TRAIN_STATUS.prc Modified : /GoalWebSharedFolders/GSDashboard/DB/update_pending.sql

Revision: 186215 Author: dgarcia Date: sábado, 23 de diciembre de 2017 11:18:14 Message: INT T0: TRENORD - Refactorizo y me llevo las interfaces a IWorkers, me llevare esta dll para usarla en otras soluciones ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.Debug.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.config Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/AbstractWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/GSDashboard.IWorkers.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/IWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/Properties Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/Properties/AssemblyInfo.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.IWorkers/packages.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/AbstractWorker.cs Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/IWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate MaterialTypeStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ResidenceStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ScenarioStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/StoreScen arioDataWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.sln

Revision: 186076 Author: dgarcia Date: miércoles, 20 de diciembre de 2017 16:27:08 Message: INT T0: TRENORD - Añado nuevas dependencias ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.sln

Revision: 185976 Author: dgarcia Date: martes, 19 de diciembre de 2017 17:19:46 Message: INT T0: TRENORD - Debemos usar colas separadas para los hilos, por que si no se pelearán ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate MaterialTypeStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ResidenceStatusWorker.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs

Revision: 185972 Author: dgarcia

76 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Date: martes, 19 de diciembre de 2017 16:53:45 Message: INT T0: TRENORD - Gestión básica del tooltip, ajustes de última hora en workers, nivelo la versión de framework que debe lanzarse. ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/App_Start/RouteConfig.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/TooltipController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/DependencyResolution/DefaultRegistry.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj.user Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/Home/SummaryTableViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_bcanadas.pubxml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Properties/PublishProfiles/DESA01_versionOficial.pubxml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Buscador.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_LateralTooltip.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Paginador.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Scripts.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_TablaEstados.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/SharedComponents/_SelectorConceptos.cs html Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Tooltip/Index.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/packages.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Helpers/GSDashboard.Helpers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Helpers/StatusHelper.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/GSDashboard.Models.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/PivotableConcept.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/Scenario.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/SummaryTableInfo.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/SummaryTableViewModelParams.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj.user Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/DashboardViewQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/GSDashboard.Queries.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/PeriodQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/PivotableConceptQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/TripsSummaryQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/GSDashboard.Repositories.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/ITripStatusDayRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/PivotableConceptsRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/TripStatusDayRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/App.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj.user Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs Modified : /GoalWebSharedFolders/GSDashboard/dictionary/DictionaryGeneral.xml

Revision: 184357 Author: dgarcia Date: sábado, 25 de noviembre de 2017 13:39:54 Message: INT T0: Añadimos el buscador, mejoras de la vista macro y también el prototooltip ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/BaseController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/LoginController.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/ProjectBaseController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/ProjectSummaryController.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/TooltipController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/AbstractSharedViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/Home/HomeViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/ProjectSummary/ProjectSummaryViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/Index.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Buscador.cshtml Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_FechasProyecto.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_LateralTooltip.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_Scripts.cshtml Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_SelectorConceptos.cshtml Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_SelectorEstados.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_SelectorPeriodos.cshtml Deleted : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_SelectorVistas.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/ProjectSummary/Index.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/ProjectSummary/_ProjectSummaryGraph.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/SharedComponents Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/SharedComponents/_GSProjectDatesView. cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/SharedComponents/_SelectorConceptos.cs html

77 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/SharedComponents/_SelectorEstados.csht ml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/SharedComponents/_SelectorVistas.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/_GSDashboardLayout.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Tooltip Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Tooltip/Index.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/packages.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/SummaryTableInfo.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/SummaryTableViewModelParams.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/TripsSummaryQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/GSDashboard.Repositories.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/packages.config Modified : /GoalWebSharedFolders/GSDashboard/dictionary/DictionaryGeneral.xml

Revision: 183876 Author: dgarcia Date: lunes, 20 de noviembre de 2017 23:14:42 Message: INT: Añadimos el model del ProjectSummary ---- Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/ProjectSummary Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/ProjectSummary/ProjectSummaryViewModel.cs

Revision: 183875 Author: dgarcia Date: lunes, 20 de noviembre de 2017 23:14:08 Message: INT: Añadimos el controlador ProjectSummary ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/App_Start/RouteConfig.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Controllers/ProjectSummaryController.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj.user Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Scripts/_references.js Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Home/_FechasProyecto.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/ProjectSummary Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/ProjectSummary/Index.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/ProjectSummary/_ProjectShortLabel.cshtml Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/ProjectSummary/_ProjectTimeline.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Views/Shared/_GSDashboardLayout.cshtml Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/Proyecto.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/SummaryTableInfo.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/SummaryTableViewModelParams.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/GSDashboard.Queries.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/ProjectSummaryQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/ProyectosQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/StatusQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/IProyectosRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/ProyectosRepository.cs Modified : /GoalWebSharedFolders/GSDashboard/dictionary/DictionaryGeneral.xml

Revision: 182443 Author: dgarcia Date: sábado, 04 de noviembre de 2017 12:36:29 Message: INT T0: STREAM PROCESSING - Añado workers para agregar trenes, graficos, residencias y materiales. Adapto las queries que se lanzan desde la web de acuerdo al nuevo enfoque multitabla. Corrección en los filtros de estado, aprovecho para refactorizarlos. ---- Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Models/Home/SummaryTableViewModel.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Startup.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/Web.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard/packages.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/GSDashboard.Models.csproj Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/PivotableConcept.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Models/Scenario.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/GSDashboard.Proxy.csproj.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/IUpdateDashboardService.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Properties/AssemblyInfo.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/UpdateDashboardService.svc Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/UpdateDashboardService.svc.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.Debug.config Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.Release.config Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Proxy/Web.config Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Queries/TripsSummaryQueries.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/ITripStatusDayRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/PivotableConceptsRepository.cs Modified : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Repositories/TripStatusDayRepository.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers

78 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/App.config Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Database Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Database/DBManager.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/GSDashboard.Workers.csproj.user Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Properties Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Properties/AssemblyInfo.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/WorkerMain.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/AbstractWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/IWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate MaterialTypeStatusWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ResidenceStatusWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate ScenarioStatusWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/Aggregate TrainStatusWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/Workers/UpdateDashboardByScenario/StoreScen arioDataWorker.cs Added : /GoalWeb/GSDashboard/branches/GSDashboard_StreamProcessing/GSDashboard.Workers/packages.config

Revision: 181921 Author: dgarcia Date: sábado, 28 de octubre de 2017 11:15:22 Message: INT T0: TRENORD - Rama para adaptar el dashboard a Stream Processing ---- Revision: 166210 Author: dgarcia Date: viernes, 17 de marzo de 2017 14:58:50 Message: INT: TRENORD - Rendimiento de la carga de la tabla. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_SelectorVistas.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers/StatusHelper.cs

Revision: 166138 Author: dgarcia Date: jueves, 16 de marzo de 2017 18:24:38 Message: INT: TRENORD - Se añade una nueva ruta que permite hacer peticiones al dashboard para devolver el HTML de la tabla en llamadas asíncronas. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/App_Start/RouteConfig.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj.user Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/DashboardView.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/DashboardViewQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/TripsSummaryQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/DashboardViewsRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/ITripStatusDayRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/TripStatusDayRepository.cs

Revision: 166137 Author: dgarcia Date: jueves, 16 de marzo de 2017 18:23:41 Message: INT: TRENORD - Interacción con los filtros, limpieza del código ---- Deleted : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/About.cshtml Deleted : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Contact.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Deleted : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_Fechas.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_FechasProyecto.cshtml Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_SelectorVistas.cshtml Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_TablaEstados.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_GSDashboardLayout.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_LateralMenuBar.cshtml Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_ModalProyectos.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_Navigation.cshtml

Revision: 165812 Author: dgarcia Date: martes, 14 de marzo de 2017 10:37:43 Message: INT: TRENORD - Visualización de trenes con su estado por día.

79 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj.user Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_FechasProyecto.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers/StatusHelper.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj.user Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/TripsSummaryQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj.user Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/ITripStatusDayRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/ProyectosRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/TripStatusDayRepository.cs

Revision: 165755 Author: dgarcia Date: lunes, 13 de marzo de 2017 16:03:16 Message: INT: TRENORD - Los datos del proyecto se toman de la vista GW_PROJECTS ---- Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_FechasProyecto.cshtml

Revision: 165754 Author: dgarcia Date: lunes, 13 de marzo de 2017 16:02:21 Message: INT: TRENORD - Adapto el proyecto para que utilice el helper de la tabla con las mejoras de rendimiento. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/DefaultRegistry.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/GSDashboard.Models.csproj Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/Proyecto.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj.user Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/ProyectosQueries.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/TripsSummaryQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj.user Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/IProyectosRepository.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/ProyectosRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/TripStatusDayRepository.cs

Revision: 165703 Author: dgarcia Date: lunes, 13 de marzo de 2017 10:46:43 Message: INT: TRENORD - Refactorizo teniendo en mente el nuevo concepto. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/DefaultRegistry.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj Deleted : /GoalWeb/GSDashboard/trunk/GSDashboard/Models/Home/HomeTableViewModel.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Login/Index.cshtml Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers/GSDashboard.Helpers.csproj Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers/Properties Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers/Properties/AssemblyInfo.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers/StatusHelper.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Helpers/packages.config Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/DashboardViewQueries.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/EntityStatusDayQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/StatusQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/DashboardViewsRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj.user Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/IStatusRepository.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/ITripStatusDayRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/StatusRepository.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/TripStatusDayRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.sln

Revision: 160087 Author: dgarcia Date: martes, 03 de enero de 2017 12:03:35 Message: INT: Carga y muestra dinámica de vistas del dashboard en el menu superior. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/DefaultRegistry.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Models/Home/HomeTableViewModel.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/DashboardView.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/GSDashboard.Models.csproj

80 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/DashboardViewQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/DashboardViewsRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/IDashboardViewsRepository.cs

Revision: 160080 Author: dgarcia Date: martes, 03 de enero de 2017 10:31:10 Message: INT: Yo y mi costumbre de dejar cosas sin subir... ---- Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/Status.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/StatusQueries.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/IStatusRepository.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/StatusRepository.cs

Revision: 160079 Author: dgarcia Date: martes, 03 de enero de 2017 10:28:16 Message: INT: Los estados son dinámicos, se cargan de base de datos. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/DefaultRegistry.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Models/Home/HomeTableViewModel.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_LateralMenuBar.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/GSDashboard.Models.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj

Revision: 159539 Author: dgarcia Date: miércoles, 21 de diciembre de 2016 18:02:42 Message: INT: Conexión astral para subir ficheros pendientes ---- Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Models/Home Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Models/Home/HomeTableViewModel.cs

Revision: 159529 Author: jordonez Date: miércoles, 21 de diciembre de 2016 17:07:55 Message: INT T0: Creamos ficheros de diccionario para GSDashboard (copia de PreferencesModule) ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Content/GoalSystems

Revision: 159429 Author: dgarcia Date: martes, 20 de diciembre de 2016 15:33:54 Message: INT: Continuo la maquetación del Dashboard. Incluyo espacio para las fechas, primera aproximación al calendario. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/_Fechas.cshtml

Revision: 159384 Author: dgarcia Date: lunes, 19 de diciembre de 2016 18:40:11 Message: INT: Añado iconos en la barra de los estados ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml

Revision: 159377 Author: dgarcia Date: lunes, 19 de diciembre de 2016 18:22:04 Message: INT: Añado botones para cerrar sesión y abrir notificaciones en la barra de navegación ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_GSDashboardMenuBarPartial.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_Navigation.cshtml

Revision: 159370 Author: dgarcia

81 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Date: lunes, 19 de diciembre de 2016 17:35:18 Message: INT: Añado menu lateral de GSDashboard ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj.user Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_GSDashboardLayout.cshtml Added : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_LateralMenuBar.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_Navigation.cshtml

Revision: 159287 Author: dgarcia Date: viernes, 16 de diciembre de 2016 14:37:29 Message: INT: Empiezo a maquetar el diseño propuesto. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Content/Materialize/css/materialize.css Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Shared/_GSDashboardLayout.cshtml

Revision: 159276 Author: dgarcia Date: viernes, 16 de diciembre de 2016 13:09:48 Message: INT: Utilizamos nueva arquitectura de dependencias compartidas del front (GSDotNetUtilities/GoalWebSharedResources) ---- Revision: 159043 Author: dgarcia Date: miércoles, 14 de diciembre de 2016 10:41:46 Message: INT: Añado clase para gestionar queries sobre permisos y funciones. ---- Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/ProfileQueries.cs

Revision: 159042 Author: dgarcia Date: miércoles, 14 de diciembre de 2016 10:40:25 Message: INT: Quito más atributos y queries que no serán usadas. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/User.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/UsersQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/IUsersRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/UsersRepository.cs

Revision: 159039 Author: dgarcia Date: miércoles, 14 de diciembre de 2016 10:28:59 Message: INT: Adecuo el Home a la jerarquía de clases que utilizamos. Añado título de vista. Elimino atributos de User que no serán usados en el Dashboard. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/HomeController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/LoginController.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Home/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/User.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/UsersQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/IUsersRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/UsersRepository.cs

Revision: 159019 Author: dgarcia Date: martes, 13 de diciembre de 2016 17:57:09 Message: INT: Cuando iniciamos sesión, redireccionamos a HomeController, lo tomaremos de base para futuros desarrollos. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Controllers/LoginController.cs

Revision: 159008 Author: dgarcia Date: martes, 13 de diciembre de 2016 17:02:29 Message: INT: Flujo de inicio de sesión contra tabla GS_USERS. ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/GSDashboard.Web.csproj

82 Stream Processing: Aplicación directa dentro de una arquitectura distribuida

Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Views/Login/Index.cshtml Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Web.Debug.config Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/Web.config Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Models/User.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/GSDashboard.Queries.csproj Deleted : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/Queries.Designer.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/Queries.resx Added : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/Queries1.Designer.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Queries/UsersQueries.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/GSDashboard.Repositories.csproj Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.Repositories/UsersRepository.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.sln

Revision: 158969 Author: dgarcia Date: martes, 13 de diciembre de 2016 11:53:13 Message: INT: La inyección de dependencias se había duplicado. Unifico en favor de DependencyResolution. ---- Deleted : /GoalWeb/GSDashboard/trunk/GSDashboard/Dependencies Added : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/ControllerConvention.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/DefaultRegistry.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/IoC.cs Added : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/StructureMapDependencyScope.cs Modified : /GoalWeb/GSDashboard/trunk/GSDashboard/DependencyResolution/StructureMapScopeModule.cs

Revision: 158959 Author: dgarcia Date: martes, 13 de diciembre de 2016 11:10:41 Message: INT: A la tercera va la vencida. GSDashboard y GSDotNetWebUtilities al mismo nivel ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.sln

Revision: 158958 Author: dgarcia Date: martes, 13 de diciembre de 2016 11:04:55 Message: INT: Corrijo las rutas de las referencias a proyectos de GSDotNetWebUtilities ---- Modified : /GoalWeb/GSDashboard/trunk/GSDashboard.sln

Revision: 158947 Author: dgarcia Date: martes, 13 de diciembre de 2016 10:04:56 Message: INT: Commit inicial. Tomamos como referencia la estructura PreferencesModule, pero solo conservamos el Login. ----

Revision: 158787 Author: dgarcia Date: viernes, 09 de diciembre de 2016 10:11:49 Message: INT: Creamos el trunk ----

83