IAvecilla/tp0

★ 0Forks 0PythonGitHub ↗Compare

README

TP0: Docker + Comunicaciones + Concurrencia

En el presente repositorio se provee un esqueleto básico de cliente/servidor, en donde todas las dependencias del mismo se encuentran encapsuladas en containers. Los alumnos deberán resolver una guía de ejercicios incrementales, teniendo en cuenta las condiciones de entrega descritas al final de este enunciado.

El cliente (Golang) y el servidor (Python) fueron desarrollados en diferentes lenguajes simplemente para mostrar cómo dos lenguajes de programación pueden convivir en el mismo proyecto con la ayuda de containers, en este caso utilizando Docker Compose.

Instrucciones de uso

El repositorio cuenta con un Makefile que incluye distintos comandos en forma de targets. Los targets se ejecutan mediante la invocación de: make <target>. Los target imprescindibles para iniciar y detener el sistema son docker-compose-up y docker-compose-down, siendo los restantes targets de utilidad para el proceso de depuración.

Los targets disponibles son:

target accion
docker-compose-up Inicializa el ambiente de desarrollo. Construye las imágenes del cliente y el servidor, inicializa los recursos a utilizar (volúmenes, redes, etc) e inicia los propios containers.
docker-compose-down Ejecuta docker-compose stop para detener los containers asociados al compose y luego docker-compose down para destruir todos los recursos asociados al proyecto que fueron inicializados. Se recomienda ejecutar este comando al finalizar cada ejecución para evitar que el disco de la máquina host se llene de versiones de desarrollo y recursos sin liberar.
docker-compose-logs Permite ver los logs actuales del proyecto. Acompañar con grep para lograr ver mensajes de una aplicación específica dentro del compose.
docker-image Construye las imágenes a ser utilizadas tanto en el servidor como en el cliente. Este target es utilizado por docker-compose-up, por lo cual se lo puede utilizar para probar nuevos cambios en las imágenes antes de arrancar el proyecto.
build Compila la aplicación cliente para ejecución en el host en lugar de en Docker. De este modo la compilación es mucho más veloz, pero requiere contar con todo el entorno de Golang y Python instalados en la máquina host.

Servidor

Se trata de un "echo server", en donde los mensajes recibidos por el cliente se responden inmediatamente y sin alterar.

Se ejecutan en bucle las siguientes etapas:

  1. Servidor acepta una nueva conexión.
  2. Servidor recibe mensaje del cliente y procede a responder el mismo.
  3. Servidor desconecta al cliente.
  4. Servidor retorna al paso 1.

Cliente

se conecta reiteradas veces al servidor y envía mensajes de la siguiente forma:

  1. Cliente se conecta al servidor.
  2. Cliente genera mensaje incremental.
  3. Cliente envía mensaje al servidor y espera mensaje de respuesta.
  4. Servidor responde al mensaje.
  5. Servidor desconecta al cliente.
  6. Cliente verifica si aún debe enviar un mensaje y si es así, vuelve al paso 2.

Ejemplo

Al ejecutar el comando make docker-compose-up y luego make docker-compose-logs, se observan los siguientes logs:

client1  | 2024-08-21 22:11:15 INFO     action: config | result: success | client_id: 1 | server_address: server:12345 | loop_amount: 5 | loop_period: 5s | log_level: DEBUG
client1  | 2024-08-21 22:11:15 INFO     action: receive_message | result: success | client_id: 1 | msg: [CLIENT 1] Message N°1
server   | 2024-08-21 22:11:14 DEBUG    action: config | result: success | port: 12345 | listen_backlog: 5 | logging_level: DEBUG
server   | 2024-08-21 22:11:14 INFO     action: accept_connections | result: in_progress
server   | 2024-08-21 22:11:15 INFO     action: accept_connections | result: success | ip: 172.25.125.3
server   | 2024-08-21 22:11:15 INFO     action: receive_message | result: success | ip: 172.25.125.3 | msg: [CLIENT 1] Message N°1
server   | 2024-08-21 22:11:15 INFO     action: accept_connections | result: in_progress
server   | 2024-08-21 22:11:20 INFO     action: accept_connections | result: success | ip: 172.25.125.3
server   | 2024-08-21 22:11:20 INFO     action: receive_message | result: success | ip: 172.25.125.3 | msg: [CLIENT 1] Message N°2
server   | 2024-08-21 22:11:20 INFO     action: accept_connections | result: in_progress
client1  | 2024-08-21 22:11:20 INFO     action: receive_message | result: success | client_id: 1 | msg: [CLIENT 1] Message N°2
server   | 2024-08-21 22:11:25 INFO     action: accept_connections | result: success | ip: 172.25.125.3
server   | 2024-08-21 22:11:25 INFO     action: receive_message | result: success | ip: 172.25.125.3 | msg: [CLIENT 1] Message N°3
client1  | 2024-08-21 22:11:25 INFO     action: receive_message | result: success | client_id: 1 | msg: [CLIENT 1] Message N°3
server   | 2024-08-21 22:11:25 INFO     action: accept_connections | result: in_progress
server   | 2024-08-21 22:11:30 INFO     action: accept_connections | result: success | ip: 172.25.125.3
server   | 2024-08-21 22:11:30 INFO     action: receive_message | result: success | ip: 172.25.125.3 | msg: [CLIENT 1] Message N°4
server   | 2024-08-21 22:11:30 INFO     action: accept_connections | result: in_progress
client1  | 2024-08-21 22:11:30 INFO     action: receive_message | result: success | client_id: 1 | msg: [CLIENT 1] Message N°4
server   | 2024-08-21 22:11:35 INFO     action: accept_connections | result: success | ip: 172.25.125.3
server   | 2024-08-21 22:11:35 INFO     action: receive_message | result: success | ip: 172.25.125.3 | msg: [CLIENT 1] Message N°5
client1  | 2024-08-21 22:11:35 INFO     action: receive_message | result: success | client_id: 1 | msg: [CLIENT 1] Message N°5
server   | 2024-08-21 22:11:35 INFO     action: accept_connections | result: in_progress
client1  | 2024-08-21 22:11:40 INFO     action: loop_finished | result: success | client_id: 1
client1 exited with code 0

Parte 1: Introducción a Docker

En esta primera parte del trabajo práctico se plantean una serie de ejercicios que sirven para introducir las herramientas básicas de Docker que se utilizarán a lo largo de la materia. El entendimiento de las mismas será crucial para el desarrollo de los próximos TPs.

Ejercicio N°1:

Definir un script de bash generar-compose.sh que permita crear una definición de Docker Compose con una cantidad configurable de clientes. El nombre de los containers deberá seguir el formato propuesto: client1, client2, client3, etc.

El script deberá ubicarse en la raíz del proyecto y recibirá por parámetro el nombre del archivo de salida y la cantidad de clientes esperados:

./generar-compose.sh docker-compose-dev.yaml 5

Considerar que en el contenido del script pueden invocar un subscript de Go o Python:

#!/bin/bash
echo "Nombre del archivo de salida: $1"
echo "Cantidad de clientes: $2"
python3 mi-generador.py $1 $2

En el archivo de Docker Compose de salida se pueden definir volúmenes, variables de entorno y redes con libertad, pero recordar actualizar este script cuando se modifiquen tales definiciones en los sucesivos ejercicios.

Ejercicio N°2:

Modificar el cliente y el servidor para lograr que realizar cambios en el archivo de configuración no requiera reconstruír las imágenes de Docker para que los mismos sean efectivos. La configuración a través del archivo correspondiente (config.ini y config.yaml, dependiendo de la aplicación) debe ser inyectada en el container y persistida por fuera de la imagen (hint: docker volumes).

Ejercicio N°3:

Crear un script de bash validar-echo-server.sh que permita verificar el correcto funcionamiento del servidor utilizando el comando netcat para interactuar con el mismo. Dado que el servidor es un echo server, se debe enviar un mensaje al servidor y esperar recibir el mismo mensaje enviado.

En caso de que la validación sea exitosa imprimir: action: test_echo_server | result: success, de lo contrario imprimir:action: test_echo_server | result: fail.

El script deberá ubicarse en la raíz del proyecto. Netcat no debe ser instalado en la máquina host y no se pueden exponer puertos del servidor para realizar la comunicación (hint: docker network). `

Ejercicio N°4:

Modificar servidor y cliente para que ambos sistemas terminen de forma graceful al recibir la signal SIGTERM. Terminar la aplicación de forma graceful implica que todos los file descriptors (entre los que se encuentran archivos, sockets, threads y procesos) deben cerrarse correctamente antes que el thread de la aplicación principal muera. Loguear mensajes en el cierre de cada recurso (hint: Verificar que hace el flag -t utilizado en el comando docker compose down).

Parte 2: Repaso de Comunicaciones

Las secciones de repaso del trabajo práctico plantean un caso de uso denominado Lotería Nacional. Para la resolución de las mismas deberá utilizarse como base el código fuente provisto en la primera parte, con las modificaciones agregadas en el ejercicio 4.

Ejercicio N°5:

Modificar la lógica de negocio tanto de los clientes como del servidor para nuestro nuevo caso de uso.

Cliente

Emulará a una agencia de quiniela que participa del proyecto. Existen 5 agencias. Deberán recibir como variables de entorno los campos que representan la apuesta de una persona: nombre, apellido, DNI, nacimiento, numero apostado (en adelante 'número'). Ej.: NOMBRE=Santiago Lionel, APELLIDO=Lorca, DOCUMENTO=30904465, NACIMIENTO=1999-03-17 y NUMERO=7574 respectivamente.

Los campos deben enviarse al servidor para dejar registro de la apuesta. Al recibir la confirmación del servidor se debe imprimir por log: action: apuesta_enviada | result: success | dni: ${DNI} | numero: ${NUMERO}.

Servidor

Emulará a la central de Lotería Nacional. Deberá recibir los campos de la cada apuesta desde los clientes y almacenar la información mediante la función store_bet(...) para control futuro de ganadores. La función store_bet(...) es provista por la cátedra y no podrá ser modificada por el alumno. Al persistir se debe imprimir por log: action: apuesta_almacenada | result: success | dni: ${DNI} | numero: ${NUMERO}.

Comunicación:

Se deberá implementar un módulo de comunicación entre el cliente y el servidor donde se maneje el envío y la recepción de los paquetes, el cual se espera que contemple:

  • Definición de un protocolo para el envío de los mensajes.
  • Serialización de los datos.
  • Correcta separación de responsabilidades entre modelo de dominio y capa de comunicación.
  • Correcto empleo de sockets, incluyendo manejo de errores y evitando los fenómenos conocidos como short read y short write.

Ejercicio N°6:

Modificar los clientes para que envíen varias apuestas a la vez (modalidad conocida como procesamiento por chunks o batchs). Los batchs permiten que el cliente registre varias apuestas en una misma consulta, acortando tiempos de transmisión y procesamiento.

La información de cada agencia será simulada por la ingesta de su archivo numerado correspondiente, provisto por la cátedra dentro de .data/datasets.zip. Los archivos deberán ser inyectados en los containers correspondientes y persistido por fuera de la imagen (hint: docker volumes), manteniendo la convencion de que el cliente N utilizara el archivo de apuestas .data/agency-{N}.csv .

En el servidor, si todas las apuestas del batch fueron procesadas correctamente, imprimir por log: action: apuesta_recibida | result: success | cantidad: ${CANTIDAD_DE_APUESTAS}. En caso de detectar un error con alguna de las apuestas, debe responder con un código de error a elección e imprimir: action: apuesta_recibida | result: fail | cantidad: ${CANTIDAD_DE_APUESTAS}.

La cantidad máxima de apuestas dentro de cada batch debe ser configurable desde config.yaml. Respetar la clave batch: maxAmount, pero modificar el valor por defecto de modo tal que los paquetes no excedan los 8kB.

Por su parte, el servidor deberá responder con éxito solamente si todas las apuestas del batch fueron procesadas correctamente.

Ejercicio N°7:

Modificar los clientes para que notifiquen al servidor al finalizar con el envío de todas las apuestas y así proceder con el sorteo. Inmediatamente después de la notificacion, los clientes consultarán la lista de ganadores del sorteo correspondientes a su agencia. Una vez el cliente obtenga los resultados, deberá imprimir por log: action: consulta_ganadores | result: success | cant_ganadores: ${CANT}.

El servidor deberá esperar la notificación de las 5 agencias para considerar que se realizó el sorteo e imprimir por log: action: sorteo | result: success. Luego de este evento, podrá verificar cada apuesta con las funciones load_bets(...) y has_won(...) y retornar los DNI de los ganadores de la agencia en cuestión. Antes del sorteo no se podrán responder consultas por la lista de ganadores con información parcial.

Las funciones load_bets(...) y has_won(...) son provistas por la cátedra y no podrán ser modificadas por el alumno.

No es correcto realizar un broadcast de todos los ganadores hacia todas las agencias, se espera que se informen los DNIs ganadores que correspondan a cada una de ellas.

Parte 3: Repaso de Concurrencia

En este ejercicio es importante considerar los mecanismos de sincronización a utilizar para el correcto funcionamiento de la persistencia.

Ejercicio N°8:

Modificar el servidor para que permita aceptar conexiones y procesar mensajes en paralelo. En caso de que el alumno implemente el servidor en Python utilizando multithreading, deberán tenerse en cuenta las limitaciones propias del lenguaje.

Condiciones de Entrega

Se espera que los alumnos realicen un fork del presente repositorio para el desarrollo de los ejercicios y que aprovechen el esqueleto provisto tanto (o tan poco) como consideren necesario.

Cada ejercicio deberá resolverse en una rama independiente con nombres siguiendo el formato ej${Nro de ejercicio}. Se permite agregar commits en cualquier órden, así como crear una rama a partir de otra, pero al momento de la entrega deberán existir 8 ramas llamadas: ej1, ej2, ..., ej7, ej8. (hint: verificar listado de ramas y últimos commits con git ls-remote)

Se espera que se redacte una sección del README en donde se indique cómo ejecutar cada ejercicio y se detallen los aspectos más importantes de la solución provista, como ser el protocolo de comunicación implementado (Parte 2) y los mecanismos de sincronización utilizados (Parte 3).

Se proveen pruebas automáticas de caja negra. Se exige que la resolución de los ejercicios pase tales pruebas, o en su defecto que las discrepancias sean justificadas y discutidas con los docentes antes del día de la entrega. El incumplimiento de las pruebas es condición de desaprobación, pero su cumplimiento no es suficiente para la aprobación. Respetar las entradas de log planteadas en los ejercicios, pues son las que se chequean en cada uno de los tests.

La corrección personal tendrá en cuenta la calidad del código entregado y casos de error posibles, se manifiesten o no durante la ejecución del trabajo práctico. Se pide a los alumnos leer atentamente y tener en cuenta los criterios de corrección informados en el campus.


Entrega

Parte 1

Ejercicio 1

Se creó un archivo entrypoint generar-compose.sh que ejecuta otro script hecho en Python llamado generador.py el cual genera el docker compose con una determinada cantidad de clientes.

El script se invoca de la siguiente manera: ./generar-compose.sh <OUTPUT_FILE> <NUM_CLIENTS>

  • OUTPUT_FILE: Nombre del archivo donde se va a escribir el docker compose
  • NUM_CLIENTS: Cantidad de servicios de cliente a escribir

Ejercicio 2

Se incluyeron dos lineas en el generador del docker compose agregando volumes tanto en el cliente como el servidor para los archivos de configuracion. Se cambiaron los comandos de COPY dentro de los Dockerfiles para no copiar los archivos de configuracion y utilizar los archivos compartidos con el host medianto los volumenes. Tambien se eliminaros las variables de entorno relacionadas al nivel de log ya que tenian preferencia por sobre las que estan en el archivo de configuracion.

Para comprobar su funcionamiento se puede ejecutar el comando de

make docker-compose-up y una vez iniciado los containers ejecutar docker exec server ls / para comprobar que el archivo evidentemente existe, tambien se puede modificar el archivo de configuracion en la maquina host y compraobar con el comando docker exec server cat /config.ini que se modificó dentro del container.

Ejercicio 3

Se creó un nuevo script llamado validar-echo-server.sh que permite chequear que el servidor este funcionando correctamente mandando un mensaje con netcat y verificando que la respuesta se la misma.

Se realiza corriendo un container con Alpine al cual se le instala netcat y se elimina una vez que recibe la respuesta, esa respuesta se comparaba con el mensaje original y se imprime por consola si el proceso fue exitoso o no.

Se puede correr de la siguiente manera:

TEST_MESSAGE=<MESSAGE_TO_SEND ./validar-echo-server.sh

  • MESSAGE_TO_SEND: Mensaje a utilizar para probar el servidor, en caso de no definir esa variable se utiliza el mensaje test por defecto.

Ejercicio 4

Se modifico al struct Client y Server para que al recibir una señal de SIGTERM finalicen su ejecucion de manera controlada.

En el cliente se agregaron las librerias os/syscall y signal para manejar la señal de interrupcion y en el servidor se agrego la libreria de signal, ambos registran los handlers de la señal y modifican una variable que hace que el loop principal se detenga.

Para comprobar dicho uso:

make docker-compose-up

Una vez este todo levantado:

docker compose -f docker-compose-dev.yaml stop -t 5

Deberiamos poder ver con los comandos docker logs client1 y docker logs server, los logs correspondientes al handleo de la señal.

Parte 2

Ejercicio 5

Se modifico el comportamiento del Cliente y el Servidor para que puedan generar y enviar un mensaje de apuesta (Cliente) y procesar y guardar las apuestas recibidas (Servidor).

El cliente debe recibir una serie de datos para formar la apuesta que son declarados como variables de ambiente. En este caso el script generador del docker compose se encarga de generar algunos datos falsos y asignarlos a estas variables donde a cada cliente se le generan algunos datos distintos para poder reconocerlos facilmente. Las variables de ambiente leidas por vyper previamente leian unicamente las variables de ambiente que tenian el prefijo CLI asi que ese mismo prefijo se utilizo para estas variables.

Cliente El cliente al inicializarse lee estas variables y se guarda una apuesta con dichos datos. A la hora de ejecutarse la funcion run el cliente enviara dos mensajes:

  1. El primer mensaje representa el tamaño total de datos que va a enviar, de este modo el servidor sabe cuanto contenido debe esperar
  2. El segundo mensaje es el mensaje de la apuesta que sigue el siguiente formato:
    AGENCIA,NOMBRE,APELLIDO,DOCUMENTO,NACIMIENTO,NUMERO
    

Luego esperara por la respuesta del servidor que debera contener el documento y el numero de la apuesta realizada. En caso de que los datos sean incorrectos o no reciba una respuesta terminara el proceso.

Servidor

El servidor procesara el mensaje de apuesta de los clientes y en caso exitoso debera guardarlas mediante la funcion store_bets y enviar una respuesta con el siguiente formato:

DOCUMENTO,NUMERO

Cuyos datos vendran de la apuesta que recibio.

Ambos tienen funciones auxiliares para leer y escribir que se encargan de chequear que la totalidad de bytes se lea y se escriba con la utilizacion de un loop, de este modo evitamos cualquier tipo de short_read y short_write.

Para probar esta funcionalidad unicamente se deben levantar los clientes y el servidor mediante:

make docker-compose-up

Se pueden revisar los logs de los diferentes servicios para chequear que las apuestas fueron enviadas, recibidas y procesadas.

Ejercicio 6

Tanto el servidor como el cliente fueron modificados para el correct envio y procesamiento de batches de apuestas, ahora un mismo mensaje podra contener varias de ellas.

Cliente

El cliente ya no se inicializa con una unica apuesta si no que se cargan todas las apuestas a enviar desde un archivo .csv que esta compartido con el host a traves de un volumen de Docker. Esto fue modificado en el generador. Todas las variables de entorno para crear la apuesta en el punto anterior fueron eliminados para mejor claridad del codigo.

Ahora hay una nueva configuracion en el cliente que se lee desde el .yaml que determina la cantidad de apuestas que va a contener un batch.

El cliente ahora enviara un mensaje con el siguiente formato para representar un batch de bets:

BET_1|BET_2|BET_3..BET_N

Manteniendo el mensaje de BET_1 con el mismo formato que en el punto anterior. A cada batch enviado el cliente espera la respuesta del cliente que contendra, las apuestas procesadas en ese batch y el total de apuestas procesadas hasta el momento de ese mensaje. El cliente corrobora que la cantidad sea la correcta.

Una vez que se mandó el ultimo batch de apuestas (que puede contener menos apuestas que el declarado en la config) el cliente envia un ultimo mensaje ALL_SENT indicandole al servidor que el proceso ya terminó y no debe procesar mas batches. Existe la posibilidad de recibir un mensaje de error de parte del servidor por algun error en el procesamiento de una apuesta, ante este caso el cliente deja de enviar el resto de apuestas pendientes y termina su proceso.

Servidor

El servidor espera por mensajes de con batches de apuestas con el formato indicado en el Cliente. Las lee en un loop hasta que el cliente envia su mensaje de finalizacion.

A cada batch recibido se llama a la funcion de store_bets para guardarlas al igual que en el punto anterior (solo que esta vez es una lista de apuestas). Asi mismo a cada batch procesado se enviar un mensaje con el siguiente formato:

BETS_PROCESSED_IN_BATCH,TOTAL_BETS_PROCESSED

Indicandole al cliente la cantidad de apuestas que proceso en este batch y la cantidad total de apuestas que ya procesó. El servidor chequea por la correctitud de las apuestas fijandose que todos los campos esten completos, en caso de que no lo estan, el Servidor, envia un mensaje de error ERR_INVALID_BET para indicarle al cliente que hay una apuesta erronea y no va a seguir procesando ninguna mas.

Para probar esta funcionalidad unicamente se deben levantar los clientes y el servidor mediante:

make docker-compose-up

Se pueden revisar los logs de los diferentes servicios para chequear que los batches fueron siendo enviados y procesados por cliente y servidor respectivamente.

Ejercicio 7

Se modifico tanto el cliente como el servidor para que ahora se pueda efectuar la loteria y obtener los ganadores una vez que todas las agencias hayan mandado todas sus apuestas.

Cliente

Se han agregado dos mensajes nuevos para el cliente:

  • Un mensaje NEW_BET indicando que se va a proceder a mandar los batches de apuestas con el formato indicado anteriormente
  • Un mensaje BET_RESULT,<AGENCIA> donde el cliente va a pedir por los resultados de las apuestas pasando en el mismo mensaje la agencia a la que pertenece

Estos se hicieron para diferenciar la situacion del cliente. El proceso y formato de mensajes para el envio de apuestas es el mismo que antes. Una vez que finaliza de mandar todas sus apuestas se inicia un loop en donde el cliente enviara sucesivos mensajes de BET_RESULT hasta que los resultados esten disponibles. El cliente en este punto espera por una respuesta del servidor indicandole:

  • Si todavia se estan procesando apuestas por lo tanto seguira pidiendo por resultados luego de un sleep de 1 segundo
  • Si su agencia no tiene ganadores, por lo tanto termina el proceso
  • Si ya estan disponibles los resultados y ya puede consultar los ganadores de su agencia

Servidor

El servidor contiene una nueva variable de configuracion definido como variables de ambiente (actualizado en el generador de docker compose) indicandole cuantas agencias van a participar en total de esta seria de apuestas. De esta manera puede generar los resultados cuando todos hayan enviado sus apuestas.

El servidor seguira recibiendo mensajes de apuestas mientras los clientes las mandan, ahora responde a los dos nuevos mensajes del cliente para diferenciar si van a mandar apuestas o estan pidiendo por resultados. En el caso en que llegue un mensaje de resultados pero estos no estan listos entonces enviara un mensaje NOT_READY. En el caso en que si esten disponibles, carga el total de apuestas con load_bets y guarda el total de los ganadores en una lista. Luego determina cuales son los ganadores de la agencia que pidio por resultados:

  • En caso de que la agencia no presente ganadores se enviara el mensaje NO_WINNERS
  • En caso contrario se envia un mensaje con el total de los ganadores con formato BET_1|BET_2|BET_3..BET_N

Para probar esta funcionalidad unicamente se deben levantar los clientes y el servidor mediante:

make docker-compose-up

Se pueden revisar los logs de los diferentes, en los clientes indicara el total de ganadores que posee y en el servidor debera loguearse que el sorteo se realizo con exito.

Parte 3

Ejercicio 8

Se modificó el servidor para soportar conexiones de cliente concurrentemente y poder procesar apuestas de dos clientes al mismo tiempo.

Se utilizo la libreia de multiprocessing del std de Python. En este caso el modelo de concurrencia utilizado es la exclusion mutua. Puntualmente se crearon tres locks y dos value proxies para compartir ciertos valores entre procesos:

  • Uno de los locks se realizo sobre el archivo donde se escriben y leen las apuestas, asi solo un proceso de Python a la vez podra realizar operaciones lo que evita que haya estados inconsistentes entre procesos y que todos tengan su turno para acceder al recurso
  • Otro lock junto a un value proxy se creo para los clientes ya finalizados, de esta manera nos aseguramos que la cantidad sea consistente y todos los procesos observen la misma cantidad de clientes finalizados y listos para obtener resultados.
  • El ultimo lock se realiza sobre la lista de apuestas ganadoras. Este lock quizas no es tan necesario, se implementó de esta manera a la hora de calcular los ganadores para evitar tener que hacerlo una vez por agencia cuando los clientes se handleaban de forma iterativa, ahora que sucede todo en paralelo el hecho de que cada proceso se encargue de obtener los ganadores quizas no es tan problematico, de igual manera opté por dejarlo. El primero proceso que consiga el lock de esa lista va a ser el encargado de llenarla con los ganadores, los demas procesos ya veran la lista llena y procedearan a chequear cuales son los de la agencia correspondiente

Tambien se creo una nueva lista con todos los procesos spawneados por el servidor, en caso de un shutdown o recibir una señal de SIGTERM se iteraran los procesos de los clientes 1 a 1 cerrando las conexiones y terminandolos

Para probar esta funcionalidad unicamente se deben levantar los clientes y el servidor mediante:

make docker-compose-up

El comportamiento sigue siendo el mismo, con grandes inputs en la cantidad de apuestas o con el maximo de apuestas por batches puesto en 1 se llega a observar una minima mejora en los tiempos desde que inicia hasta que manda los ganadores pero puede ser simple casualidad por que son unos pocos segundos

Contributors

FrancoBarIAvecillaEzetowerspablodrocan-zuLaCumbancha

Issues