Esta aplicación tiene como objetivo leer archivos con extensión .xlsx con un formato (esquema) determinado por el usuario. Esto permite copiar los datos de un archivo binario a una colección de mongodb con verificaciónes de tipos.
Se debe tener instalado:
- git
- docker (v20.10.7)
- docker-compose (v1.29.2)
En caso de no querer usar docker:
Se utilizan los siguientes puertos:
3000(api)5672(rabbitmq)27017(mongodb)
Por lo que ninguno de ellos se debe estar utilizando previo al despliegue de la aplicación o resultará en un error.
Como primer requisito se debe clonar el repositorio:
git clone git@github.com:fotscode/excel-reader.git
cd excel-readerSegun la herramienta de build que se quiera utilizar los comandos son diferentes, por lo que se enumeraran diferentes alternativas con el mismo objetivo: desplegar la aplicación.
Utilizando el archivo compose.yml y los Dockerfile's provistos, solo se necesita realizar la siguiente directiva:
docker-compose up -dLevantar los servicios de mongodb y de RabbitMQ usando docker-compose:
docker-compose up mongodb rabbitmqLa utilización de yarn/npm, en este caso, es equivalente por lo que se pueden reemplazar los siguientes comandos con yarn. El primer paso es instalar las dependencias:
npm installPara inicializar la API se utiliza el siguiente comando:
npm run devLuego para inicializar el consumidor de RabbitMQ, en otra terminal, se utiliza:
npm run consumerDevA su vez, otra opción es utilizar los archivos compilados por tsc. Para realizar esto se proveen las siguientes directivas:
npm run build
npm run preview # api [en una terminal, o utilizar &]
npm run consumerPreview # consumidor [en otra terminal]Luego de desplegar la aplicación, para utilizarla se recomienda usar postman, que sirve para interactuar con la API y que es de gran ayuda para el endpoint de subir un archivo. Se provee en docs/postman.json una colección de postman con ejemplos de estos endpoints junto a las configuraciones de autenticación.
Los endpoints de la aplicación son envueltos por una capa de autenticación y autorización. La autenticación se realiza mediante el header Authorization y como método de autenticación se utiliza Basic authentication.
Como ejemplos se agregan a la base de datos tres usuarios:
admin:admincon el roladmin(permisos[REQUEST, UPLOAD]) tiene el headerAuthorization: Basic YWRtaW46YWRtaW4=watcher:watchercon el rolwatcher(permisos[REQUEST]) tiene el headerAuthorization: Basic d2F0Y2hlcjp3YXRjaGVyempty:emptysin roles (por ende sin permisos) tiene el headerAuthorization: Basic ZW1wdHk6ZW1wdHk=
En caso de fallar la autenticación se retorna un 401, en caso de que falle la autorización se retorna un 403.
Existen dos endpoints en la aplicación y se describen a continuación
En este endpoint se sube un archivo y se encola la tarea, para que esta pueda ser tomada por un consumidor de RabbitMQ, el cual procesará el archivo. Require el permiso UPLOAD.
Para mandar el archivo se lo colocá en el body de la request, este body tiene un formato multipart/form-data. Dentro del campo file se coloca el archivo y en el campo format se coloca el esquema.
Ejemplos de format pueden ser:
{name: String, age: Number, nums: Array<Number>}{age: Number, name: String, nums?: Array<Number>}
Como respuesta se espera el UUID de la tarea encolada.
Se proveen en la carpeta examples/ ejemplos de archivos con extensión .xlsx:
name_age_nums_provided.xlsx, archivo con columnasname,age,numscon 2 filas:Esteban,12,"3,8,1,9,100,34,78,32,97,12"24,Texto,
name_age_nums_200k.xlsx, archivo con columnasname,age,numscon 200 mil filas respetando el órden y los numeros como opcionales (array de tamaño[0,9]).name_age_nums_5000length.xlsx, archivo con columnasname,age,numscon mil filas respetando el órden y los numeros como opcionales (array de tamaño[0,5000]).
Con el UUID obtenido del endpoint anterior, se puede consultar el estado de la tarea. Requiere el permiso REQUEST.
Los estados posibles son cuatro:
pending: cuando fue encolada pero no fue tomada por ningún consumidorprocessing: cuando fue tomada por un consumidordone: cuando la tarea terminó exitosamenteerror: cuando la tarea falla por alguna causa externa al procesamiento
A su vez la respuesta contiene los errores de procesamiento, indicando fila y columna del error. Estos se pueden paginar utilizando los parametros de query limit y page, por ejemplo:
GET status/UUID-status?limit=5&page=2
Un gráfico simple de la arquitectura pensada se puede ver en esta imágen:
Se utiliza typescript como lenguaje de programación y express como framework de backend.
Por otra parte se utiliza RabbitMQ como broker de mensajes. La utilización de un broker proviene de la necesidad de mantener la API lo más ligera posible, mientras que un consumidor de la cola de mensajes se encarga de realizar el procesamiento, liberando a la interfaz HTTP del procesamiento.
Para guardar el estado de la tarea y los errores que se encuentra en la misma se utiliza mongodb. A nivel de aplicación la interacción entre los servicios se puede ver de la siguiente manera:
UploadFile, ProcessFile y RequestStatus son las funcionalidades claves (use-cases) de la aplicación. En mayor detalle se puede ver la organización del código como varios anillos, dónde las dependencias van hacia el centro, siendo el centro independiente del resto (siguiendo Clean Architecture).
Se realizaron tests utilizando vitest por su velocidad y facilidad con typescript y ESModules. Para correr los tests se puede utilizar npm o yarn, utilizando la directiva npm run test o yarn run test respectivamente.


