Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JCN-112-Log #1

Merged
merged 31 commits into from Aug 7, 2019
Merged

JCN-112-Log #1

merged 31 commits into from Aug 7, 2019

Conversation

Nataniel4
Copy link
Contributor

JCN-112-LOG
JCN-112 Crear paquete log

LINK AL TICKET
https://fizzmod.atlassian.net/browse/JCN-112

DESCRIPCIÓN DEL REQUERIMIENTO
1.1. Se requiere crear un paquete nuevo para la creación de logs
1.2. Los logs se deben crear en el servicio S3
1.3. Las credenciales aws_access_key_id y aws_secret_access_key se deben tomar de variables de entorno y que cada MS las tendrá configuradas.

DESCRIPCIÓN DE LA SOLUCIÓN
Se desarrollo lo solicitado en el ticket

@Nataniel4 Nataniel4 requested a review from juanhapes July 26, 2019 12:51
README.md Outdated Show resolved Hide resolved
lib/log.js Outdated Show resolved Hide resolved
lib/log.js Outdated Show resolved Hide resolved
tests/log-test.js Outdated Show resolved Hide resolved
tests/log-test.js Outdated Show resolved Hide resolved
tests/log-test.js Show resolved Hide resolved
Copy link
Member

@jormaechea jormaechea left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Te dejé varios comentarios.
En mi opinión, hiciste código demasiado complejo para una tarea super simple: hacer una request con reintentos.

Con respecto a los tests: hubo un buen motivo para hacer un "mock" de AWS con tanta complejidad? Alcanzaba con hacer algo como

sandbox.stub(AWS, 'S3')
	.returns({
		putObject: someSinonStub
	});

y después assertear que se haya llamado a someSinonStub correctamente.
Hay mucha complejidad innecesaria ahí también

lib/log.js Outdated
const MAX_TIMEOUT = 500;

const S3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acá no hace falta pasarle las keys. De hecho, cuando se ejecute en lambda no hay keys.
Simplemente no lo pasás, y en el docker-compose.yml se monta el siguiente volumen - ~/.aws:/root/.aws

Ver el MS de router, que ya está implementado de esta manera.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PD: Documentar en el README.

lib/log.js Outdated
if(!log || typeof log !== 'object' || Array.isArray(log))
throw new LogError('Invalid log', LogError.codes.INVALID_LOG);

const logDate = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perdón, pero qué necesidad de declarar un objeto con una prop y 3 getters, si se va a usar una sola vez, y los getters devuelven exactamente lo mismo cada vez que se los llama?

Es extremadamente más simple, fácil de entender y performante hacer simplemente

const date = log.date_created ? new Date(log.date_created * 1000) : new Date();
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, 0);
const day = date.getDate().toString()
		.padStart(2, 0);

lib/log.js Outdated
if(!log.id)
log.id = UUID();

S3.putObject({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todos los métodos de los SDK de Amazon se pueden usar con Promise en lugar de callbacks.

Para este ejemplo, podés hacer algo asi:

return S3.putObject({ ... }).promise();

Y del otro lado lo manejás con un await.
(Ver comentario sobre el método add de cómo simplificarlo)

lib/log.js Outdated

class Log {

static add(bucket, log) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Demasiado complejo para una tarea tan simple. Mirá qué simple se puede dejar todo esto, sin definir funciones adentro de funciones, con intervalos cuando ya le pusiste un timeout a la request.

static async add(bucket, log, attempts = 0) {

	try {
		await this._add(bucket, log);
	} catch(err) {
		if(attempts >= MAX_ATTEMPTS)
			throw new LogError(`Unable to put the log into S3, max attempts reached: ${err.message}`, LogError.codes.S3_ERROR);

		return this.add(bucket, log, ++attempts);
	}
}

Por otro lado, en el catch podrías manejar la lógica de no hacer reintentos para los dos error codes INVALID_BUCKET y INVALID_LOG. No tiene sentido intentar guardar un log 3 veces si ya sabés que va a volver a fallar.

lib/log.js Outdated

const MAX_TIMEOUT = 500;

const S3 = new AWS.S3({ httpOptions: { timeout: MAX_TIMEOUT } });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const S3 = new AWS.S3({ httpOptions: { timeout: MAX_TIMEOUT } });
const S3 = new AWS.S3({ httpOptions: { timeout: MAX_TIMEOUT } });

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Que raro eso, no sale en el editor

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debe coincidir el tab-stop justo en un caracter..

lib/log.js Outdated
} catch(err) {

if(err.name === 'LogError')
throw err;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ojo con estos throw.. La aplicación no debería explotar por no poder guardar un log.
Por el momento, simplemente loggearía en la consola que no se pudo guardar el log, y el motivo.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrijo: no sé si loggear en la consola es una buena decisión en un package.
Quizás sea una mejor decisión emitir un evento de node..

Para eso, deberías crear un event emitter fuera de la clase

const EventEmitter = require('events');
const emitter = new EventEmitter();

Y agregar un método .on() a la clase Log, que haga algo asi

static on(event, callback) {
	emitter.on(event, callback);
}

Y finalmente, emitir el evento:

emitter.emit('create-error', log, err);

Si alguien quisiera suscribirse a los errores al crear logs, haría algo asi:

const Log = require('@janiscommerce/log');
Log.on('create-error', (log, err) => {
	// do something
});


const MockRequire = require('mock-require');

MockRequire('aws-sdk', AWS);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Este MockRequire creería que no hace falta.
Por otro lado, un par de lineas más abajo estás creando un stub de AWS.S3, y nunca lo estás restoreando. Ojo ahí.

});

sandbox.assert.calledWithExactly(putObjectStub, expectedParams);
sandbox.assert.callCount(putObjectStub, 4);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 llamados? El máximo de intentos está setteado como 3..

@jormaechea jormaechea merged commit 7f0654b into master Aug 7, 2019
@Nataniel4 Nataniel4 deleted the JCN-112-log branch September 3, 2019 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants