This is the challenge project for ml
- Setup
- Cloning repo
- Installing dependencies
- Running application
- Testing
- Prod Urls
- Challenge
- Observations
Technology Stack
Back-End: Node, Serverless, Jest, Docker.
Infrastructure in AWS: Lambdas, CloudFormation, S3, Dynamo.
VSCode
https://code.visualstudio.com/
Serverless
npm i -g serverless
Docker
https://www.docker.com
AWSCLI
https://aws.amazon.com/cli/
git clone https://github.com/Moreanco/beyond.git
In the root directory:
npm i
Run local database
(The first time)
docker-compose up --build npm run migrate
(Each time you want to run locally dynamodb - Open in a different terminal. It needs to be open the connection)
Run api application
npm start
npm t
POST - https://mh1tszk5qe.execute-api.us-west-2.amazonaws.com/prod/mutants
GET - https://mh1tszk5qe.execute-api.us-west-2.amazonaws.com/prod/stats
configure aws with: (Need aws credentials)
aws configure npm run deploy
Magneto quiere reclutar la mayor cantidad de mutantes para poder luchar contra los X-Men. Te ha contratado a ti para que desarrolles un proyecto que detecte si un humano es mutante basándose en su secuencia de ADN. Para eso te ha pedido crear un programa con un método o función con la siguiente firma (En alguno de los siguiente lenguajes: Java / Golang / C-C++ / Javascript (node) / Python / Ruby):
boolean isMutant(String[] dna);
// Ejemplo Java
En donde recibirás como parámetro un array de Strings que representan cada fila de una tabla de (NxN) con la secuencia del ADN. Las letras de los Strings solo pueden ser: (A,T,C,G), las cuales representa cada base nitrogenada del ADN.
MUTANTE ['ATGCGA', 'CAGTGC', 'TTATGT', 'AGAAGG', 'CCCCTA', 'TCACTG'];
NO MUTANTE ['ATGCGA', 'ACCTGC', 'TAATGT', 'AGAAGG', 'TCCTTA', 'TCACTG'];
Sabrás si un humano es mutante, si encuentras más de una secuencia de cuatro letras iguales, de forma oblicua, horizontal o vertical.
Ejemplo (Caso mutante): String[] dna = {"ATGCGA","CAGTGC","TTATGT","AGAAGG","CCCCTA","TCACTG"}; En este caso el llamado a la función isMutant(dna) devuelve “true”.
Desarrolla el algoritmo de la manera más eficiente posible.
Desafíos:
Nivel 1: Programa (en cualquier lenguaje de programación) que cumpla con el método pedido por Magneto.
Nivel 2: Crear una API REST, hostear esa API en un cloud computing libre (Google App Engine, Amazon AWS, etc), crear el servicio “/mutant/” en donde se pueda detectar si un humano es mutante enviando la secuencia de ADN mediante un HTTP POST con un Json el cual tenga el siguiente formato: POST → /mutant/ { “dna”:["ATGCGA","CAGTGC","TTATGT","AGAAGG","CCCCTA","TCACTG"] } En caso de verificar un mutante, debería devolver un HTTP 200-OK, en caso contrario un 403-Forbidden
Nivel 3: Anexar una base de datos, la cual guarde los ADN’s verificados con la API. Solo 1 registro por ADN. Exponer un servicio extra “/stats” que devuelva un Json con las estadísticas de las verificaciones de ADN: {“count_mutant_dna”:40, “count_human_dna”:100: “ratio”:0.4} Tener en cuenta que la API puede recibir fluctuaciones agresivas de tráfico (Entre 100 y 1 millón de peticiones por segundo). Test-Automáticos, Code coverage > 80%. Entregar: ● Código Fuente (Para Nivel 2 y 3: En repositorio github). ● Instrucciones de cómo ejecutar el programa o la API. (Para Nivel 2 y 3: En README de github). ● URLdelaAPI(Nivel2y3).
Si bien dije que fue una estimacion fue dos semanas, esto lo arranque el domingo 31/05. La razon es que estaba en transicion de cambio de cliente y me iba a estar liberadndo recien despues 29/05. Dejo aclarado un par de cosas que me hubiesen gustado cambiar en el challenge.
-
El acceso a dynamo.
Si bien se puede acceder porque di permiso a todo (asignando *) no es lo mejor. Lo ideal seria que haya exportado la tabla (Cloudformation export) y asignado en el recurso como ImportValue, por tema de tiempo y compromiso con la entrega del examen dejo esto mencionado. -
Acceso a la base de datos.
Las lambdas hoy en dia estan escribiendo directamente a la base de datos. La consigna dice que puede tener mucho trafico, entonces podria haber agregado un sqs o kinesis entre el medio de la lambda y dynamo (Seria un sqs + una lambda que procese el topic correspondiente) para la escritura a la base de datos. De ese modo seria escalable. Fui por lambdas porque se manejan muy bien para cuando se tiene que escalar y el costo es bajo. -
Dynamo Access Patterns.
Quisiera dejar en claro los access patterns que elegi para que la app funcione.Get Metadata for certain person.
PK (PartitionKey): #METADATA#.
SK (Sort Key): #<HUMAN|MUTANT>#.Get Total for each type
SK: #<HUMAN|MUTANT>#.
PK: #METADATA#.La busqueda de esta ultima seria de la siguiente manera:
SK= #HUMAN# and begins_with(PK, #METADATA#).
La tabla tiene una partition key (PK) y una sort key (SK) y como ya tengo ese "indice" cree un reverse index de manera tal de ya tener gratis el access pattern para obtener el total
---------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---|---|---|---|---|---|
All files | 98.29 | 95.12 | 100 | 98.13 | |
lambdas/api/mutants | 100 | 100 | 100 | 100 | |
post.js | 100 | 100 | 100 | 100 | |
lambdas/api/stats | 100 | 100 | 100 | 100 | |
get.js | 100 | 100 | 100 | 100 | |
libs | 93.1 | 50 | 100 | 91.3 | |
DynamoIO.js | 86.67 | 50 | 100 | 84.62 | 6-8 |
HttpMessage.js | 100 | 100 | 100 | 100 | |
HttpStatusCodes.js | 100 | 100 | 100 | 100 | |
shared/constants | 100 | 100 | 100 | 100 | |
index.js | 100 | 100 | 100 | 100 | |
shared/models | 100 | 100 | 100 | 100 | |
humanModel.js | 100 | 100 | 100 | 100 | |
shared/services | 100 | 100 | 100 | 100 | |
dnaService.js | 100 | 100 | 100 | 100 | |
humanService.js | 100 | 100 | 100 | 100 | |
--------------------- | --------- | ---------- | --------- | --------- | ------------------- |