Trabajo Práctico
Introducción
Nos encontramos en el desarrollo de un backend para un sistema distribuido y de alta disponibilidad destinado a la venta, gestión y validación de entradas para eventos deportivos de gran escala.
El sistema debe gestionar la venta simultánea de miles de ubicaciones para diversos eventos en diferentes estadios, garantizando la consistencia de los datos en un entorno de alta concurrencia donde múltiples usuarios intentan comprar potencialmente los mismos asientos de forma concurrente.
Así mismo, el sistema se utilizará para validar los ingresos durante los eventos, para lo cual debe soportar altísimos niveles de carga, evitando que una misma entrada se pueda utilizar más de una vez.
Los usuarios finales interactuarán con el sistema a través de terminales de venta, aplicaciones móviles, aplicaciones embebidas en molinetes, y sitio de ventas web que se comunicarán a través de APIs a nuestro backend.
Objetivo
Implementar un conjunto de aplicaciones distribuidas que modelen el sistema de ticketing descrito. Se requiere el uso del lenguaje Rust para explotar sus garantías de seguridad en el manejo de memoria y su modelo de concurrencia sin condiciones de carrera, fundamentales para la integridad del sistema.
Requerimientos
-
El sistema debe poder listar los eventos deportivos en oferta y sus asientos disponibles en tiempo real.
-
El sistema debe soportar múltiples peticiones de reserva simultáneas sobre un mismo evento. Cada operación de compra debe ser atómica y aislada, asegurando que no se produzcan sobreventas ni inconsistencias en el inventario de entradas.
-
El sistema debe poder soportar compras de múltiples asientos en la misma operación, y debe sugerir conjuntos de asientos idealmente contiguos para las mismas.
-
El sistema entregará las entradas compradas de forma digital, enviando un correo electrónico con la confirmación de las mismas.
-
El sistema realizará los cobros a través de una API externa de pagos.
-
El sistema validará la entrada al momento del ingreso (por simplificación será simplemente un id). Debe no permitir que la misma entrada se utilice más de una vez.
-
El sistema deberá proveer una API de analytics con información en tiempo real de las ventas, así como del estado de ingreso para los eventos en vivo.
-
Por cuestiones impositivas, el sistema debe correr un proceso diario reportando todas las ventas concretadas, y un proceso mensual que totalice las operaciones realizadas con el procesador de pagos, agrupadas por su estado final.
Requerimientos no funcionales
-
El estado del sistema debe ser consistente. No pueden haber entradas reservadas ni entregadas a más de un usuario, como tampoco cobros efectivos a usuarios que no tengan asegurada una entrada, o entradas entregadas sin su correspondiente pago. Tampoco puede más de un usuario ingresar el día del evento con la misma entrada.
-
Resiliencia y Tolerancia a Fallos: El sistema debe ser capaz de recuperarse ante la caída de nodos individuales. Si un servidor de transacciones falla, otros nodos deben poder retomar la gestión de las operaciones pendientes sin pérdida de datos.
-
Escalabilidad y Comunicación Eficiente: La arquitectura debe minimizar el overhead de red mediante la propagación inteligente de actualizaciones de estado, optimizando el tráfico entre los distintos servidores de la infraestructura distribuida.
-
Carga: el sistema debe soportar alta demanda, considerando que miles de usuarios intentarán realizar compras y validar entradas en simultáneo.
-
Durante la fase de desarrollo y pruebas, se desarrollarán servidores de mocking para el envío de correos y API de pagos, los cuales registrarán en sus logs las operaciones, debiendo los mismos también poder simular fallas y negaciones de servicio.
-
El proyecto deberá ser desarrollado en lenguaje Rust, usando las herramientas de la biblioteca estándar.
-
Cada instancia de cada aplicación debe ejecutarse en un proceso independiente.
-
Todas las entradas y salidas de las aplicaciones deberán ser vía sockets, consola, o en su defecto archivos de texto (csv, json, etc.). En ningún caso se utilizarán GUIs, TUIs o cualquier otro tipo de interfaz.
-
No se permite utilizar crates externos, salvo los explícitamente mencionados en este enunciado, los utilizados en las clases, o los autorizados expresamente por los profesores.
-
El código fuente debe compilarse en la última versión stable del compilador y no se permite utilizar bloques unsafe.
-
El código deberá funcionar en ambiente Unix / Linux.
-
El programa deberá ejecutarse en la línea de comandos.
-
La compilación no debe arrojar warnings del compilador, ni del linter clippy.
-
Las funciones y los tipos de datos (struct) deben estar documentadas siguiendo el estándar de cargo doc.
-
El código debe formatearse utilizando cargo fmt.
-
Cada tipo de dato implementado debe ser colocado en una unidad de compilación (archivo fuente) independiente.
Desarrollo
Durante el desarrollo del sistema se deberán tomar decisiones de arquitectura. Por citar algunas:
- Definición de los algoritmos a utilizar para mantener la consistencia y transaccionalidad.
- Cómo mantener el sistema resiliente ante alta demanda.
- Cómo evitar la pérdida de información ante caídas de nodos.
- Utilizar programación asincrónica o hilos para atender sockets.
- Cómo implementar los analytics en vivo.
- Cómo implementar la generación de informes en batch.
Para la decisión sobre las mismas, se deberán implementar prototipos de las diferentes opciones para cada una y realizar una evaluación formal con métricas que ayuden a determinar cuál será la utilizada en la versión final. Las métricas deberán incluir uso de memoria, uso de CPU, tiempos de respuesta y análisis comparativos de la complejidad del código.
Todos los recursos utilizados para el análisis incluyendo código, ejecuciones y prompts deberán ser parte de los entregables del proyecto. Se podrán utilizar herramientas externas para el análisis de carga, por ejemplo apache ab.
Seguimiento y entregas
La resolución del presente proyecto es en grupos de tres integrantes. No se aceptan grupos de otra cantidad de miembros.
Durante las semanas de cursada se tendrán encuentros de avance con algunos grupos en simultáneo, donde cada grupo hará una pequeña presentación del progreso de su proyecto, las decisiones tomadas, los resultados obtenidos, los prompts utilizados y las correcciones que tuvieron que hacer sobre los mismos para llegar a los resultados esperados; y cualquier otra información que sea relevante para compartir lecciones aprendidas y dar nota del proceso de aprendizaje y avance del proyecto.
Hacia el final del cuatrimestre habrá una presentación final de cada grupo con los profesores de la materia donde deberán resumir todo el proceso de aprendizaje además de mostrar su solución funcionando correctamente ante situaciones de stress.
Fechas
| Fecha | Evento |
|---|---|
| 14 de Octubre de 2026 | Introducción al enunciado del TP |
| 28 de Octubre, 3, 4, 10, 11 y 17 de Noviembre de 2026 | Seguimiento de TP (a coordinar) |
| 24 de Noviembre de 2026 | Entrega Final (código e informes) |
| 24, 25 de Noviembre, 1 y 2 de Diciembre de 2026 | Presentación final |
Evaluación
Calificación
La calificación del trabajo individual y se evaluará la participación de cada miembro del grupo tanto en el desarrollo como en la presentación. La calificación final del mismo será nominal y podrá ser INSUFICIENTE, REENTREGA, APROBADO o DESTACADO; modulando la nota del alumno en el parcial para el cierre de la nota de cursada. INSUFICIENTE implica la desaprobación y necesidad de recursar la materia.
Entregas parciales
Las diferentes presentaciones del grupo deberán dar nota de un progreso en su aprendizaje y el dominio de las competencias de la materia, y de la práctica profesional en general. El no cumplir con las mismas puede implicar la desaprobación temprana del trabajo y la necesidad de recursar la materia.
Principios teóricos y corrección de bugs
Los estudiantes presentarán el diseño, código y comportamiento en vivo de su solución, con foco en el uso de las diferentes herramientas de concurrencia.
Deberán poder explicar, desde los conceptos teóricos vistos en clase, cómo se comportará potencialmente su solución ante problemas de concurrencia (por ejemplo ausencia de deadlocks).
En caso de que la solución no se comportara de forma esperada, deberán poder explicar las causas y sus posibles rectificaciones.
Casos de prueba
Se someterá a la aplicación a diferentes casos de prueba que validen la correcta aplicación de las herramientas de concurrencia y la resiliencia de las distintas entidades.
Organización del código
El código debe organizarse respetando los criterios de buen diseño y en particular aprovechando las herramientas recomendadas por Rust.
Se prohíbe el uso de bloques unsafe.
Tests automatizados
La entrega debe contar con tests automatizados que prueben diferentes casos. Se considerará en especial aquellos que pongan a prueba el uso de las herramientas de concurrencia.
Artefactos
Toda fuente, archivo, ejecución y prompt utilizado para el desarrollo de la solución y las presentaciones deberá ser incluido en el repositorio, dando nota explícita de las modificaciones y mejoras aportadas por los alumnos respecto de las bases. El uso de fuentes, incluyendo IA generativa sin supervisión por los alumnos implica la desaprobación automática.
Presentación final
El trabajo deberá entregarse para la fecha estipulada. La presentación fuera de término sin coordinación con antelación con el profesor influirá negativamente en la nota final.