diff --git a/packages/shared/infrastructure/RabbitMQEventBus.ts b/packages/shared/infrastructure/RabbitMQEventBus.ts index 66ccbfd..308b8da 100644 --- a/packages/shared/infrastructure/RabbitMQEventBus.ts +++ b/packages/shared/infrastructure/RabbitMQEventBus.ts @@ -27,10 +27,6 @@ export class RabbitMQEventBus implements EventBus { async consume(queue: string, callback: (msg: ConsumeMessage | null) => void) { // Comproaciones antes de escuchar if (this.channel == undefined) throw new Error("[RMQ] Canal no iniciallizado"); - - // El binding (cola -> [routingkey] -> exchange) lo hago por configuracion. Meter colas a demanda? - //await this.channel.prefetch(1) - await this.channel.consume(queue, callback) } @@ -55,7 +51,7 @@ export class RabbitMQEventBus implements EventBus { try { this.connection = await this.createConnection(); if (this.connection == undefined) throw new Error("[RMQ] Error crecreando la conexion") - this.channel = await this.createConfirmChannel() + this.channel = await this.createChannel() this.channel.on("close", () => { console.log("[RMQ] Canal desconectado") setTimeout(async () => { @@ -116,14 +112,14 @@ export class RabbitMQEventBus implements EventBus { console.log(`[RMQ] Reintentando conexion`) }); - connection.on("disconnect", (err) => { - console.error(`[RMQ] Servidor Rabbitmq desconectado, reintentando ...`) + connection.on("disconnect", (err: unknown) => { + console.error(`[RMQ] Servidor Rabbitmq desconectado, reintentando ... :: ${err}`) }) return connection; } - protected async createConfirmChannel() { + protected async createChannel() { if (this.connection == undefined) throw new Error("[RMQ] Intentando crear un canal sin una conexion") const channel = this.connection.createChannel({ json: true, diff --git a/packages/sim-consumidor-objenious/aplication/JWT.service.ts b/packages/sim-consumidor-objenious/aplication/JWT.service.ts index 276a483..861147b 100644 --- a/packages/sim-consumidor-objenious/aplication/JWT.service.ts +++ b/packages/sim-consumidor-objenious/aplication/JWT.service.ts @@ -38,7 +38,7 @@ type AuthHeaders = { exp: number, } -const PRIVATE_KEY_PATH = __dirname + "/../obj.pem" +const PRIVATE_KEY_PATH = env.OBJ_PEM_PATH const GET_TOKEN_URL = "https://idp.docapost.io/auth/realms/GETWAY/protocol/openid-connect/token" const REFRESH_TOKEN_URL = GET_TOKEN_URL diff --git a/packages/sim-consumidor-objenious/aplication/Sim.controller.ts b/packages/sim-consumidor-objenious/aplication/Sim.controller.ts new file mode 100644 index 0000000..994237e --- /dev/null +++ b/packages/sim-consumidor-objenious/aplication/Sim.controller.ts @@ -0,0 +1,57 @@ +import { EventBus } from "#shared/domain/EventBus.port"; +import { ConsumeMessage } from "amqplib"; +import { SimUseCases } from "./Sim.usecases"; + +export class SimController { + private eventBus: EventBus; + private useCases: SimUseCases + + constructor( + eventBus: EventBus, + useCases: SimUseCases + ) { + this.eventBus = eventBus + this.useCases = useCases + + } + + public async activateSim(msg: ConsumeMessage | null) { + return async () => { + if (!this.validateActivationMsg(msg)) { + throw new Error("Error consumiendo el mensaje no es valido") + } + const msgData = Buffer.from(JSON.parse(msg?.content.toString("utf-8") || "{}").data) + console.log("Mensaje procesado", String(msgData)) + + // Caso de uso de activaciones + await this.useCases.activate({ + dueDate: new Date().toString(), + identifier: { + identifierType: "ICCID", + identifiers: ["1234"] + } + })() + // TODO: comprobar el resultado de la opreacion + this.eventBus.ack(msg!) + } + } + + public async pauseSim(msg: ConsumeMessage | null) { + return async () => { + if (!this.validateActivationMsg(msg)) { + throw new Error("Error consumiendo el mensaje no es valido") + } + const msgData = Buffer.from(JSON.parse(msg?.content.toString("utf-8") || "{}").data) + console.log("Mensaje procesado", String(msgData)) + } + } + + /** + * TODO: + * - Loguear motivos de la no validacion + */ + private validateActivationMsg(msg: ConsumeMessage | null) { + if (msg == undefined) return false; + return true; + } +} diff --git a/packages/sim-consumidor-objenious/aplication/Sim.router.ts b/packages/sim-consumidor-objenious/aplication/Sim.router.ts new file mode 100644 index 0000000..99c917e --- /dev/null +++ b/packages/sim-consumidor-objenious/aplication/Sim.router.ts @@ -0,0 +1,48 @@ +/** + * Dirige cada mensaje dependiendo de el tipo de accion que contenga + */ + +import { ConsumeMessage } from "amqplib"; +import { SimController } from "./Sim.controller"; + +export class SimRouter { + private simController: SimController + + private routeMap: Map void> = new Map() + + constructor(simController: SimController) { + this.simController = simController + + // No me gusta que se defina en el constructor + this.routeMap = new Map([ + ["activate", this.simController.activateSim], + ["pause", this.simController.pauseSim], + ]) + this.route = this.route.bind(this) + } + + public route(msg: ConsumeMessage | null) { + if (msg == undefined) { + console.error("Mensaje vacio") + return; + } + + const routingKey = msg.fields.routingKey + const action = routingKey.split(".")[2] + + if (action == undefined) { + console.error("La routing key no tiene una accion definida") + console.error(msg.fields) + } + + const accionEjecutable = this.routeMap.get(action) + + if (accionEjecutable == undefined) { + console.error("La accion del mensaje no tiene un controlador asociado") + } else { + console.log("Ejecutado operacion", action) + } + + } + +} diff --git a/packages/sim-consumidor-objenious/aplication/Sim.usecases.ts b/packages/sim-consumidor-objenious/aplication/Sim.usecases.ts new file mode 100644 index 0000000..27a362a --- /dev/null +++ b/packages/sim-consumidor-objenious/aplication/Sim.usecases.ts @@ -0,0 +1,48 @@ +import { ActivationData } from "#domain/DTOs/objeniousapi" +import { HttpClient } from "#shared/infrastructure/HTTPClient" + +// TODO: Pasar a un archivo de DTOs + + +export class SimUseCases { + private httpClient: HttpClient + + constructor(args: { + + httpClient: HttpClient + }) { + this.httpClient = args.httpClient + } + + public activate(activationData: ActivationData) { + const OPERATION_URL = "/actions/preactivate" + return async () => { + const req = this.httpClient.client.post(OPERATION_URL, { + ...activationData + }) + + try { + const e = await req + console.log("Activacion con exito", e.data) + } catch (error) { + console.error("Error activando ", error) + } + } + } + + public pause(activationData: ActivationData) { + const OPERATION_URL = "/actions/pause" + return async () => { + const req = this.httpClient.client.post("/actions/pause", { + ...activationData + }) + + try { + const e = await req + console.log("Sim pausada con exito", e.data) + } catch (error) { + console.error("Error pausa", error) + } + } + } +} diff --git a/packages/sim-consumidor-objenious/aplication/SimActivation.controller.ts b/packages/sim-consumidor-objenious/aplication/SimActivation.controller.ts deleted file mode 100644 index 17d84b8..0000000 --- a/packages/sim-consumidor-objenious/aplication/SimActivation.controller.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { EventBus } from "#shared/domain/EventBus.port"; -import { ConsumeMessage } from "amqplib"; -import { SimActivationUseCase } from "./SimActivation.usecase"; - -export class SimActivationController { - private eventBus: EventBus; - private useCases: { - activation: SimActivationUseCase - } - - constructor( - eventBus: EventBus, - useCases: { - activation: SimActivationUseCase - } - ) { - this.eventBus = eventBus - this.useCases = useCases - // No se si hay un sistema mejor - // convertor en const () => {} para conservar el contexto?? - this.activateSim = this.activateSim.bind(this) - } - - public async activateSim(msg: ConsumeMessage | null) { - if (!this.validateActivationMsg(msg)) { - throw new Error("Error consumiendo el mensaje no es valido") - } - const msgData = Buffer.from(JSON.parse(msg?.content.toString("utf-8") || "{}").data) - console.log("Mensaje procesado", String(msgData)) - - // Caso de uso de activaciones - await this.useCases.activation.run({ - dueDate: new Date().toString(), - identifier: { - identifierType: "ICCID", - identifiers: ["1234"] - } - }) - // TODO: comprobar el resultado de la opreacion - this.eventBus.ack(msg!) - } - - /** - * TODO: - * - Loguear motivos de la no validacion - */ - private validateActivationMsg(msg: ConsumeMessage | null) { - if (msg == undefined) return false; - return true; - } -} diff --git a/packages/sim-consumidor-objenious/aplication/SimActivation.usecase.ts b/packages/sim-consumidor-objenious/aplication/SimActivation.usecase.ts index 89ac540..454adab 100644 --- a/packages/sim-consumidor-objenious/aplication/SimActivation.usecase.ts +++ b/packages/sim-consumidor-objenious/aplication/SimActivation.usecase.ts @@ -1,20 +1,6 @@ +import { ActivationData } from "#domain/DTOs/objeniousapi" import { HttpClient } from "#shared/infrastructure/HTTPClient" -// TODO: Pasar a un archivo de DTOs - -export type ActivationData = { - dueDate: string, // isodate - filter?: {} // no se si hace falta - identifier: { - identifiers: string[] - identifierType: "IMSI" | "MSISDN" | "REFERENCE" | "ICCID" | "IMEI" - } -} - -export type ResponseError = { - error: string, - detail: Object[] -} export class SimActivationUseCase { private httpClient: HttpClient diff --git a/packages/sim-consumidor-objenious/domain/DTOs/objeniousapi.ts b/packages/sim-consumidor-objenious/domain/DTOs/objeniousapi.ts new file mode 100644 index 0000000..75caf1a --- /dev/null +++ b/packages/sim-consumidor-objenious/domain/DTOs/objeniousapi.ts @@ -0,0 +1,14 @@ + +export type ActivationData = { + dueDate: string, // isodate + filter?: {} // no se si hace falta + identifier: { + identifiers: string[] + identifierType: "IMSI" | "MSISDN" | "REFERENCE" | "ICCID" | "IMEI" + } +} + +export type ResponseError = { + error: string, + detail: Object[] +} diff --git a/packages/sim-consumidor-objenious/index.ts b/packages/sim-consumidor-objenious/index.ts index 9080c6f..83c8580 100644 --- a/packages/sim-consumidor-objenious/index.ts +++ b/packages/sim-consumidor-objenious/index.ts @@ -1,22 +1,23 @@ import { startRMQClient } from "#config/eventBus.config" import { httpInstance } from "#config/httpClient.config" -import { SimActivationController } from "aplication/SimActivation.controller" -import { SimActivationUseCase } from "aplication/SimActivation.usecase" +import { SimController } from "aplication/Sim.controller" +import { SimRouter } from "aplication/Sim.router" +import { SimUseCases } from "aplication/Sim.usecases" async function startWorker() { const rmqClient = await startRMQClient() const httpClient = httpInstance - const simActivationController = new SimActivationController( + const simActivationController = new SimController( rmqClient, - { - activation: new SimActivationUseCase({ - httpClient: httpClient - }) - } + new SimUseCases({ + httpClient: httpClient + }) ) + const simRouter = new SimRouter(simActivationController) - rmqClient.consume("sim.objenious", simActivationController.activateSim) + // de momento solo una cola por simplificar + rmqClient.consume("sim.objenious", simRouter.route) } startWorker()