GithubHelp home page GithubHelp logo

nikitastetskiy / micro-calendario Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 2.0 5.75 MB

Microservicio basado en consulta de eventos de un calendario.

Home Page: micro-calendario-git-master.nikitastetskiy.vercel.app

License: GNU General Public License v3.0

JavaScript 94.98% Dockerfile 5.02%
hacktoberfest hacktoberfest2020 hacktoberfest-accepted

micro-calendario's Introduction

Micro Calendario

Proyecto que pertenece a la asignatura Infraestructura Virtual (IV).

Build Status

Descripción

Esta API web se basará en la consulta de eventos. He elegido este problema, porque tengo muchas complicaciones a la hora de organizar fechas. Así que he pensado que la mejor solución sería un bot personal de telegram, dónde puedas crear eventos y consultar los mismos de una manera eficiente.

Para poder instalar la aplicación emplearemos los siguientes comandos. Es necesario tener node instalado para poder ejecutar los comandos npm:

npm install

Para instalar las dependencias del proyecto.

npm test

Para testear el proyecto.

npm run lint

Para ejecutar Eslint y Prettier en el proyecto.

Documentación

En el plan del proyecto se desarrollará toda la información correspondiente a la planificación del proyecto y las distintas entregas. Se explicarán las pautas seguidas, la creación y la configuración de diferentes ficheros.

Aun así, a continuación puede disponer de toda la información esencial del proyecto:

Lenguaje de programación

He utilizado Javascript, ya que es un lenguaje ampliamente popular y que para mí es totalmente nuevo. Aunque por lo que he podido leer es un lenguaje bastante sencillo, rápido y muy versátil. Otra de sus famosas ventajas es que es multiplataforma y además es muy útil para desarrollar páginas dinámicas y aplicaciones web.

Todo lo relacionado con esta explicación se encuentra en este enlace.
Gestor de paquetes

He elegido Npm, el cual es el gestor por defecto para Node.js y además un entorno de ejecución para Javascript. También lo he utilizado como herramienta de construcción, además este gestor funciona a través de un fichero JSON, ya que se realiza un seguimiento de módulos instalados. En este fichero se contendrá información del proyecto, tal como el nombre, descripción, autor, etc.

De momento es una herramienta de construcción muy simple, dispone de funciones que por ahora abarcan todas nuestras necesidades, tales como instalar las distintas dependencias, módulos, paquetes y la ejecución de scipts, que por ahora solamente es testing. Además su metodología de programación es bastante sencilla, funciona como ya dije junto con un fichero JSON, el cual contiene:

  • Todos los módulos necesarios para un proyecto y sus versiones instaladas.
  • Todos los metadatos de un proyecto, como el autor y la licencia, entre otros.
  • Secuencias de comandos que se pueden ejecutar para automatizar tareas del proyecto.
Los archivos JSON correspondientes: package.json y package-lock.json.

Todo lo relacionado con esta explicación se encuentra en este enlace.
Testing

Si no está 'testeado', está roto. Para llevar a cabo los test, he escogido Jest, el cual es un marco de prueba de JavaScript bastante sencillo de entender. Taskfile apuntará a util.test.js, el cual será ejecutado mediante package.json. JSON interviene en esta sección mediante la gestión de la instalación de dependencias con el comando npm install --save-dev jest. Se tendrá que modificar la parte de scripts para poder ejecutar npm test.

No podemos considerar a los test como una herramienta, ya que se interpreta a los test como parte integral del proceso de desarrollo y el código. Aun así, Jest es un framework de testing generalista que podemos utilizar en cualquier situación, en el cual podemos crear, ejecutar y estructurar pruebas. El lado positivo de estas pruebas es que puedes tener control sobre el funcionamiento de lo que estás creando, puedes incluso realizar diferentes tipos de pruebas a un mismo bloque de código y de esta manera puedes saber que tan susceptible es esa parte de código.

La principal ventaja es que supone un buen flujo de trabajo con Npm y Node. Además posee una gran documentación y comunidad, lo cual hace más fácil y ágil su aprendizaje. Tampoco hace falta una biblioteca de aserciones, ya que está incluida.

Todo lo relacionado con esta explicación se encuentra en este enlace.
Docker

Se ha creado el Dockerfile y .dockerignore siguiendo las recomendaciones de buenas prácticas. También se ha creado la build correspondiente en mi perfil de Dockerhub.

Estos son los contenedores que he podido probar localmente:

Contenedor Base Tiempo de Construcción Tiempo de Ejecución (testing) Tamaño
node:14-stretch 109.3s 14.91s 978MB
node:14-buster 26.7s 15.884s 947MB
alpine:3.12 12.4s 13.592s 90.5MB
node:14-slim 14.2s 14.382s 202MB

Al principio he usado buster y la versión stretch, ya que son contenedores que lo tienen todo, aunque buster más nuevo, debido a que es la versión Debian 10. Al ser por así decirlo una versión genérica te incluye todas las necesidades, aunque el tiempo de construcción y el tamaño es bastante desfavorable. Por lo que me he inclinado en versiones más slim, en la cual la más ventajosa es 14-slim, ya que tarda muy poco en construirse y el tamaño de la imagen también es bastante pequeño, aun así, incluye todo lo necesario para el funcionamiento. También he utilizado una versión no oficial que incluía únicamente node (mhart/alpine-node:slim).

Aunque finalmente me he decantado por la versión Alpine, ya que es muy ligera, pese a que utiliza /bin/sh como shell, apk como packagemanger y algunas librerías inusuales. Esta imagen es mucho mejor, ya que aunque hayamos quitado YARN en como mejora de optimización en node:14-slim (aquí el commit correspondiente), la imagen ubuntu sigue ocupando bastante espacio. Por lo que al utilizar alpine, su última versión disponible, nos ahorramos bastante espacio. También borramos la caché y los archivos JSON innecesarios.

Se ha utilizado node como usuario, ya que no se necesita realizar instalaciones como superusuario, todo esto por motivos de seguridad. Posteriormente se ha utilizado también una optimización de la imagen limpiando la caché de npm, además de hacer un clean install. También se ha removido archivos no necesario, como los JSON. Otros ejemplos de optimización vienen siendo el uso de herramientas como squash o podman.

DockerHub

Se ha configurado y automatizado DockerHub:

drawing

GitHub Container Registry

Se ha configurado y enlazado GHCR:

drawing

Ejecución y prueba:


        docker pull nikitastetskiy/micro-calendario
        
docker run -t -v `pwd`:/test nikitastetskiy/micro-calendario

Si usamos GitHub Container Registry:


        docker pull ghcr.io/nikitastetskiy/micro-calendario:latest
        
docker run -t -v `pwd`:/test ghcr.io/nikitastetskiy/micro-calendario:latest

Todo lo relacionado con esta explicación se encuentra en este enlace.
Integración continua (Travis, Shippable y GitHub Actions)

  • Travis: se ha configurado el fichero travis, siguiendo las buenas prácticas, de tal manera que pueda ejecutar los test junto al docker que ya teníamos implementado anteriormente. También se ha añadido una pequeña integración continua en el mismo archivo, esto se realiza mediante deploy y pages, el cual hace que se me actualice gh-pages autómaticamente.
  • float:left
  • Shippable: se ha configurado el fichero shippable de una manera muy parecida a travis, pero ahora en vez de utilizar el docker, se ha utilizado directamente node para comprobar los test.
  • float:left
  • GitHub actions - workflow: se ha configurado el fichero ghcr y el fichero linter-prettier. El fichero ghcr se ha utilizado para publicar un paquete docker en la parte de packages de github, testea el contenedor docker y se publica. El fichero linter-prettier se usa para corregir la sintaxis y el estilo del código con reglas definidas por mí y configuraciones generales.
  • float:left Todo lo relacionado con las pautas de creación y configuración se encuentra en este enlace.
Sistemas serverless

  • Vercel: lo único que tenemos que hacer es conectarnos con github en la plataforma Vercel. Posteriormente elegir y importar el código fuente de nuestro proyecto. Finalmente para enlazar el proyecto y nuestro directorio de trabajo, lanzamos vercel y lo configuramos, es decir lo linkeamos a nuestra plataforma de Vercel. Así pues cada vez que hagamos push se desplegará en estado production, aunque también podemos desplegarla antes como dev o hacer deploy para tener una preview de su funcionamiento. Gracias a este sistema he podido automatizar las funciones serverless. En su historia de usuario podemos ver todos los pasos seguidos para que este sistema funcione correctamente. Para su funcionamiento primero me he creado la cuenta y agregado el repositorio de la asignatura. Luego he inicializado Vercel en mi repo y he agregado la carpeta api y el archivo vercel.json para la configuración. En la carpeta se encuentran las distintas funciones. El archivo de configuración se ha realizado debido a que solo quiero que sean accesibles distintas rutas del proyecto y que solamente se use los métodos GET y POST. float:left Como función serverless, primero he realizado un Hola Mundo el cual también funciona cuando accedemos a la raíz del proyecto. La segunda función devuelve un string en formato JSON con una fecha introducida por el usuario. Aunque la fecha a devolver tendrá un formato diferente al introducido. El archivo 5.json contiene lo mismo que si hacemos la petición a Vercel. El código de la segunda función está comentado y explicado. La tercera función tiene la misma funcionalidad que la segunda, aunque ahora dedicada para Telegram.

    Los despliegues de vercel se pueden comprobar en estas URLs y en este commit como ejemplo:
  • float:left
  • Netlify: igual que en Vercel, para que se nos actualice y haga build en cada push a GitHub lo que tenemos que hacer es registrarnos con nuestra cuenta, inyectar Netlify a nuestro repositorio y una vez hecho esto, inicializamos Netlify en el directorio del repo y linkeamos nuestro proyecto con el que tenemos en Netlify. Para la implementación de Netlify también me he basado en varias funciones, en este caso template, la primera de ellas es un Hola Mundo para poder probar el funcionamiento correcto del intercambio de datos en Netlify. Luego he probado la funcion Protected, la cual devuelve un JSON con el formato de salida "NOT ALLOWED" en caso de no identificar al usuario. He usado el redireccionamiento adecuado para esta situación en caso de que se quiera acceder a cualquier otro sitio que no sean las funciones implementadas. Finalmente también he implementado GraphQL, el cual nos facilita la consulta y manipulación de datos. He pensado que sería una opción interesante controlar las peticiones desde el cliente y no del servidor, como pasa en Rest. De esta manera podemos definir lo que pedimos. De momento solo están implementadas unas funciones básicas en las que pedimos un query endpoint Hola Mundo, varios types de Autores y Eventos que ante la petición devuelven un JSON. De momento no hay una base de datos, por lo que todas las peticiones se realizan en dicha función. float:left float:left Como resumen, las funciones de Vercel se encuentran en la carpeta (api) y son tres, cada una con una funcionalidad diferente (Hola Mundo: código y función, Calendar: código y función, Calendar-bot: código y función)). Las funciones de Netlify se encuentran en la carpeta (functions) y son tres, cada una con una funcionalidad diferente (Hola Mundo: código y función, Protected: código y función, GraphQL: código y función)). Las funciones de Netlify se encuentran organizadas cada una en su propio directorio, ya que han sido creadas de esa manera según create y debido que son templates.

  • Telegram bot: este sistema va a estar compaginado con las funciones implementadas en Vercel. El primer paso es crear el token gracias a Bot Father. El funcionamiento del bot depende de la integración de los webhooks, esta opción es mucho más ventajosa que polling, ya que no estamos constantemente preguntando si hay cambios, sino que la función serverless funcionará cuando se envíe un mensaje. Para integrar el webhook solo tenemos que realizar una petición a esta URL https://api.telegram.org/botTOKEN_BOTFATHER/setWebHook?url=URL_FUNCTION_VERCEL. Sustituir TOKEN_BOTFATHER por el token correspondiente y URL_FUNCTION_VERCEL por la URL de la función, que en mi caso es https://micro-calendario.vercel.app/calendar-bot. Aunque para acceder a las funciones del bot solamente es posible con objetos JSON, por lo que si accedemos la URL nos dará un error. Aunque esto es fácil de arreglar con un if al principio del programa que nos compruebe si existe un body o mensaje en sí. Utilizamos el fórmato JSON porque necesitamos saber el ID del chat para que haya un intercambio de mensajes, también el contenido del mensaje y diversos datos como el nombre o la fecha del mensaje. Un ejemplo de JSON sería:

    
            "update_id":646911460,
            "message":{
                "message_id":93,
                "from":{
                    "id":10000,
                    "is_bot":false,
                    "first_name":"Jiayu",
                    "username":"jiayu",
                    "language_code":"en-US"
                },
                "chat":{
                    "id":10000,
                    "first_name":"Jiayu",
                    "username":"jiayu",
                    "type":"private"
                },
                "date":1509641174,
                "text":"/help"
            }
            
    Aquí puede ver el funcionamiento del bot y la función. Aunque puede probar el bot en este enlace. float:left
  • Todo lo relacionado con las pautas de creación y configuración se encuentra en este enlace.
Diseño y test de un microservicio

He realizado varias comparaciones, pero finalmente me he decidido por Express.js. Para nuestra aplicación he realizado algunos testeos con varios frameworks sobre las propias funciones de la aplicación y no un Hola Mundo, incluidos Hapi (commit correspondiente de la prueba y commit correspondiente del test) y Express (commit correspondiente de la prueba y commit correspondiente del test). Ambos frameworks son bastante rápidos (los test han tenido solamente 1 segundo de diferencia) y cumplen con su funcionalidad. Ahora bien, he elegido Express porque después de realizar el mismo test numerosas veces daba mejores resultados que Hapi, esto es posible a que Express guarde en la caché distintas operaciones que hagamos para no tener que repetirlas. Para nuestra aplicación es un factor clave.

Otro factor es que Express utiliza middleware para proporcionar acceso a la canalización de solicitudes / respuestas, es decir, acceso a los objetos de solicitud / respuesta req y res de Node. Una aplicación Express "encadena" el middleware para actuar sobre solicitudes y respuestas. Cada componente de middleware tiene un trabajo único y bien definido que hacer, manteniendo las preocupaciones aisladas dentro de cada componente. Hapi, por el contrario, usa plugins para ampliar sus capacidades. Los plugins se configuran en tiempo de ejecución mediante código. Existen plugins que cumplen con las funciones de middleware aunque los middlewares están diseñados generalmente para hacer cosas como verificar la autenticación entre páginas y los plugins para importar y configurar bibliotecas. Además Hapi generalmente se usa en proyectos más grandes y express para más pequeños, como este. Esto es debido por temas de escalabilidad.

Todas las rutas se han configurado en este archivo. Los test correspondientes en este archivo.

Siguiendo las buenas prácticas, he tomado como referencia la página de Express, por lo que para la realización de un registro correcto o logs he usado winston. Ya que el uso de console.log() o console.err() son funciones síncronas cuando canalizan a un terminal o un archivo, por lo que no son adecuadas para producción, a menos que canalice la salida a otro programa. Winston es una biblioteca de registro simple y universal con soporte para múltiples transportes. Esto es lo que más me ha llamado la atención, ya que un transporte es esencialmente un dispositivo de almacenamiento. Cada instancia de un registrador Winston puede tener varios transportes configurados en diferentes niveles de registro. Winston se ha configurado en este archivo.

Se ha utilizado middleware gracias a Express. Las funciones de middleware son funciones que tienen acceso al objeto de solicitud (req), al objeto de respuesta (res) y a la siguiente función de middleware en el ciclo de solicitud/respuestas de la aplicación. Se ha usado en el enlace del middleware de nivel de aplicación a una instancia del objeto de aplicación utilizando las funciones app.use() y app.METHOD(), donde METHOD es el método HTTP de la solicitud que maneja la función de middleware (por ejemplo, GET, PUT o POST) en minúsculas.

También se ha configurado Docker para que los test de las rutas funcionen también en Travis y Shippable. Aquí el issue correspondiente.

Todo lo relacionado con las pautas de creación y configuración se encuentra en este enlace.

Despliegue de una aplicación en un PaaS

Comparando varios servicios PaaS, finalmente me he decidido que la plataforma de despliegue para mi aplicación sea Heroku. No he cogido OpenShift porque primero necesita usar PostgreSQL, que en realidad es bastante sencillo de implementar, es más, en este proyecto empecé a usar PostgreSQL y luego tuve que moverlo a MongoDB, aunque esto lo explicaré más adelante. Otra de las limitaciones de OpenShift es que el almacenamiento se expira a los 60 días, algo que en mi aplicación es bastante crucial. También tiene que dormir 18 horas en un periodo de 72h. Mientras que en Heroku tienes un límite de horas por dynos, es decir, que si organizas bien las horas puedes tener un despliegue activo en casi todo el momento. En general, los dynos son mucho más flexibles que las aplicaciones de OpenShift.

Para la configuración de Heroku, me he descargado su cinturón de herramientas. Luego he accedido con mis credencias con heroku login y he creado un archivo index para la ejecución de npm start. Heroku funciona con git, por lo que todos los commits se han reflejado en este issue y para subirlo a la plataforma se usa git push heroku master. Ahora bien, hay tantos commits probando la ejecución del programa porque básicamente Telegram solo acepta peticiones por https, algo que nos proporciona Heroku y que yo no puedo probar en local. Aunque si se podría con herramientas como Postman Canary. Aun así, index tendría que cumplir el próposito de las rutas creadas anteriormente, aun así he tenido que configurar una ruta de nuevo para el correcto funcionamiento de Telegram, ya que mi intención inicial era crear un bot. Al ser un webhook, solo recibo peticiones post y luego las tengo que diferenciar con los comandos que me proporcione el mensaje del chat.

Finalmente, para la ejecución correcta de mi aplicación he tenido que crear una base de datos con MongoDB Atlas. He elegido esta opción porque principalmente necesitaba una base de datos NoSQL, es decir que haya un objeto por usuario y que ese objeto tenga un array de eventos. A medida que lo estaba haciendo, me encontré con muchos fallos a la hora de implementar la clase, por lo que al final no lo implementé como array, pero continué usando MongoDB. La clase dónde implementé MongoDb se encuentra en este archivo. Para el uso correcto de base de datos, implementé un script en js dónde lo ejecuto gracias al Scheduler de Heroku. Lo que hago en ese script es recorrer los eventos expirados y enviarlos con una request por https a través de la api de telegram. Este script se puede ejecutar cada hora.

Aquí una prueba del funcionamiento:

Para conectar y activar los despliegues automáticos de Heroku. Tenemos que añadir nuestro repositorio en Heroku y activar los deploys automáticos para la rama master.

Todo lo relacionado con las pautas de creación y configuración se encuentra en este enlace.

Enlaces a códigos y clases

Todo lo relacionado con las pautas de creación y configuración se encuentra en este enlace.

api

Enlaces a issues, milestones e historias de usuario

  • En este enlace se encuentran los issues cerrados.
  • En este enlace se encuentran los milestones cerrados.
  • Se han añadido las Historias de Usuario con su label correspondiente. Aquí se puede consultar las diferentes HU:
    • HU1: Consulta de eventos.
    • HU2: Consulta específica de eventos.
    • HU3: Creación de eventos.
    • HU4: Configuración de Docker.
    • HU5: Instalación de ESLint y Prettier.
    • HU6: Testing.
    • HU7: Integración continua.
    • HU8: Vercel.
    • HU9: Netlify.
    • NO-HU: Telegram bot.
    • NO-HU-: PaaS.
Todo lo relacionado con las pautas de creación y configuración se encuentra en este enlace.

Enlaces de interés

  • Herramientas: Herramientas que se hayan implementado en el proyecto, dónde se explicará su debido uso y funcionamiento.
  • IV: Repositorio de la asignatura Infraestructura Virtual.
  • GH Pages.

Autor

Nikita Stetskiy github

micro-calendario's People

Contributors

nikitastetskiy avatar

Stargazers

Manu Hidalgo Carmona avatar

Watchers

 avatar

micro-calendario's Issues

Mejorar descripción

Mejorar la descripción del proyecto y especificar más sobre el uso de este.

Actualizar YAML

Hay que actualizar el archivo YAML con las correspondencias del hito 2.

Unas tareas de arreglo

  • Eliminar lo del telegram.js.
  • Eliminar dependencias que no hagan falta.
  • Arreglar el docker.
  • Probar request-promise.
  • Mejorar el index y poner lo necesario en routes.
  • Cambiar las fechas para que sean universales.
  • GH-Pages (lo de br).
  • Errores o mejores que hay en las notas de iv.
  • Puede que añadir algo como esto también.

HU8: Vercel (Sistemas Serverless)

Como requisito de usuario, necesito el despliegue correcto y funcional, con documentación de la conexión entre el repo en GitHub y Vercel para despliegue continuo.

HU3: Creación de eventos

En este requisito, el usuario deberá poder crear los eventos que el usuario quiera en el calendario. Se tendrá que hacer de una manera sencilla y eficiente, posiblemente mediante comandos.

HU6: Testing

Como usuario debo saber que mi código esta testeado, en este momento debo realizarlo con las herramientas de sintaxis correcta.

Instalar los archivos JSON

Instalar este tipo de archivos, para los test y diferentes modulos. Se utilizara también para los distintos frameworks y organizar paquetes etc.

HU4: Configuración de Docker

En esta historia de usuario tendré que elegir de manera correcta y justificada del contenedor base. Siguiendo buenas prácticas, y adaptándolo de forma correcta a las clases o módulos que se están testeando.

Además subir el contenedor correctamente a Docker Hub y la documentación de la actualización automática.

Mejorar la clase evento

Necesito mejorar el constructor y algunas de las funciones de la clase, como el Set. Son funciones básicas en este hito, aunque hay que hacer que tengan más sentido.

HU5: Instalación de ESLint y Prettier

Como usuario necesito que los linters analicen mi código, y a partir de una serie de reglas definidas por mi, nos va a mostrar los errores que estamos cometiendo en nuestro código. Prettier se va a encargar de mantener nuestro código limpio.

HU9: Netlify (Sistemas Serverless)

Como requisito de usuario, necesito el despliegue correcto y funcional, con documentación de la conexión entre el repo en GitHub y Netlify para despliegue continuo.

Avanzar con los test

Hay que avanzar con los test, después de instalar los JSON. Así que hay que intentar cubrir todos los test posibles de todas las funciones posibles

Telegram bot (Sistemas Serverless)

Como requisito de usuario, necesito el despliegue correcto y funcional, con documentación de la conexión entre el repo en GitHub, Vercel y el Bot de Telegram para despliegue continuo. EL bot de Telegram tiene que funcionar mediante las funciones de Vercel y los webhooks configurados correctamente.

Buena redacción

Completar la redacción correspondiente a la entrega 3 del proyecto.

Actualizar el README

Hay que actualizar el README con las correspondencias del hito 2 y demás archivos como el plan.

Creación de clases y esqueleto inicial

Necesito crear el conjunto del esqueleto inicial, como las rutas, las vistas, librerías y lo público para diferentes tipos de dependencias y módulos. A la vez crearé un paquete de tipo JSON.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.