Monitorizacion de las operaciones lanzadas a objenious
This commit is contained in:
5
.env
5
.env
@@ -14,8 +14,9 @@ RABBITMQ_VHOST=sim-vhost
|
||||
|
||||
# Hay cosas que unificar de varios servicios
|
||||
POSTGRES_DB=postgres
|
||||
POSTGRES_DATABASE=postres
|
||||
POSTGRES_HOST=postgresql-sim-1
|
||||
POSTGRES_DATABASE=postgres
|
||||
#POSTGRES_HOST=postgresql-sim
|
||||
POSTGRES_HOST=localhost
|
||||
POSTGRES_PORT=5432
|
||||
DEV_POSTGRES_PORT=5432
|
||||
POSTGRES_USER=postgres
|
||||
|
||||
@@ -7,7 +7,7 @@ drop domain if exists imsi_type cascade;
|
||||
CREATE DOMAIN imsi_type as varchar(15);
|
||||
|
||||
|
||||
CREATE table if not exists sim_car (
|
||||
CREATE table if not exists sim_cards (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
imei imei_type,
|
||||
iccid iccid_type,
|
||||
@@ -91,8 +91,8 @@ CREATE TABLE if not exists sim_subscription_operations (
|
||||
),
|
||||
|
||||
CONSTRAINT fk_subscription_id
|
||||
FOREIGN KEY(subscription_id)
|
||||
REFERENCES sim_subscriptions(id)
|
||||
FOREIGN KEY(sim_id)
|
||||
REFERENCES sim_subscription(id)
|
||||
);
|
||||
|
||||
-- Se supone que indica un cambio
|
||||
|
||||
@@ -17,13 +17,13 @@ CREATE TABLE if not exists objenious_operation (
|
||||
last_change_date TIMESTAMP NOT NULL DEFAULT now(),
|
||||
end_date TIMESTAMP,
|
||||
error TEXT,
|
||||
status status_enum, -- Por definir los status que va a usar
|
||||
)
|
||||
status status_enum
|
||||
);
|
||||
|
||||
-- operaciones pendientes para revisar
|
||||
CREATE INDEX pending_operations
|
||||
CREATE INDEX IF NOT EXISTS pending_operations
|
||||
ON objenious_operation(start_date)
|
||||
WHERE end_date IS NULL
|
||||
WHERE end_date IS NULL;
|
||||
|
||||
CREATE TABLE if not exists objenious_operation_change (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
@@ -35,8 +35,7 @@ CREATE TABLE if not exists objenious_operation_change (
|
||||
new_mass_action_id TEXT,
|
||||
CONSTRAINT fk_operation_id
|
||||
FOREIGN KEY(operation_id) REFERENCES objenious_operation(id)
|
||||
)
|
||||
|
||||
CREATE INDEX fk_operation_change
|
||||
ON objenious_operation_change(operation_id)
|
||||
);
|
||||
|
||||
CREATE INDEX operation_change
|
||||
ON objenious_operation_change(operation_id);
|
||||
|
||||
145
deployment/database/init.sql
Normal file
145
deployment/database/init.sql
Normal file
@@ -0,0 +1,145 @@
|
||||
-- eliminar los drop para prod
|
||||
drop domain if exists imei_type cascade;
|
||||
CREATE DOMAIN imei_type as varchar(15);
|
||||
drop domain if exists iccid_type cascade;
|
||||
CREATE DOMAIN iccid_type as varchar(22);
|
||||
drop domain if exists imsi_type cascade;
|
||||
CREATE DOMAIN imsi_type as varchar(15);
|
||||
|
||||
|
||||
CREATE table if not exists sim_cards (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
imei imei_type,
|
||||
iccid iccid_type,
|
||||
imsi imsi_type,
|
||||
user_id BIGINT,
|
||||
subscription_id BIGINT,
|
||||
created_at TIMESTAMP,
|
||||
last_update TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE if not exists sim_envio (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
codigo_origen TEXT,
|
||||
codigo_distrito TEXT,
|
||||
pedido_id BIGINT,
|
||||
sim_id BIGINT,
|
||||
|
||||
fecha_envio TIMESTAMP,
|
||||
fecha_email TIMESTAMP,
|
||||
is_preactivado BOOLEAN,
|
||||
fecha_devolucion TIMESTAMP,
|
||||
created_at TIMESTAMP,
|
||||
|
||||
CONSTRAINT fk_sim_id
|
||||
FOREIGN KEY(sim_id) REFERENCES sim_cards(id)
|
||||
);
|
||||
|
||||
-- Mock, No es parte de SIMs
|
||||
CREATE TABLE if not exists sf_subscription (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY
|
||||
);
|
||||
|
||||
-- No habria que meterle las propiedades del tipo de subscripcion
|
||||
CREATE TABLE if not exists sim_subscription_types (
|
||||
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
subscription TEXT NOT NULL,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE if not exists sim_company (
|
||||
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
name TEXT,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE sim_subscription (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
company_id INT,
|
||||
subscription_type_id INT,
|
||||
sim_id BIGINT,
|
||||
order_id BIGINT,
|
||||
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
|
||||
CONSTRAINT fk_sim_id
|
||||
FOREIGN KEY(sim_id) REFERENCES sim_cards(id),
|
||||
|
||||
CONSTRAINT fk_company_id
|
||||
FOREIGN KEY(company_id) REFERENCES sim_company(id),
|
||||
|
||||
CONSTRAINT fk_subscription_type_id
|
||||
FOREIGN KEY(subscription_type_id) REFERENCES sim_subscription_types(id)
|
||||
);
|
||||
|
||||
CREATE TABLE if not exists sim_subscription_operations (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
sim_id BIGINT,
|
||||
operation_type TEXT NOT NULL,
|
||||
happened_at TIMESTAMP,
|
||||
|
||||
CONSTRAINT valid_operations CHECK (
|
||||
operation_type in ('free','preactivate','activate','pause','cancel')
|
||||
),
|
||||
|
||||
CONSTRAINT fk_subscription_id
|
||||
FOREIGN KEY(sim_id)
|
||||
REFERENCES sim_subscription(id)
|
||||
);
|
||||
|
||||
-- Se supone que indica un cambio
|
||||
CREATE TABLE sim_subscription_historic (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
subscription_id BIGINT,
|
||||
iccid iccid_type,
|
||||
company_id INT
|
||||
);
|
||||
|
||||
CREATE TYPE status_enum AS ENUM ('noRequestID','noMassID','running','finished','error','other');
|
||||
|
||||
-- Tabla para gestionar las peticiones de cambio de objenious.
|
||||
-- Para una o mas lineas se pueden lanzar operacione que no sabemos
|
||||
-- con certeza cuando van a terminar.
|
||||
CREATE TABLE if not exists objenious_operation (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
retry_count INT DEFAULT 0,
|
||||
max_retry INT DEFAULT 5,
|
||||
max_date_retry TIMESTAMP DEFAULT NULL,
|
||||
iccids TEXT,
|
||||
request_id TEXT,
|
||||
mass_action_id TEXT,
|
||||
operation TEXT NOT NULL,
|
||||
start_date TIMESTAMP NOT NULL DEFAULT now(),
|
||||
last_change_date TIMESTAMP NOT NULL DEFAULT now(),
|
||||
end_date TIMESTAMP,
|
||||
error TEXT,
|
||||
status status_enum
|
||||
);
|
||||
|
||||
-- operaciones pendientes para revisar
|
||||
CREATE INDEX IF NOT EXISTS pending_operations
|
||||
ON objenious_operation(start_date)
|
||||
WHERE end_date IS NULL;
|
||||
|
||||
CREATE TABLE if not exists objenious_operation_change (
|
||||
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
|
||||
operation_id BIGINT,
|
||||
creation_date TIMESTAMP NOT NULL DEFAULT now(),
|
||||
error TEXT,
|
||||
new_status status_enum,
|
||||
new_request_id TEXT,
|
||||
new_mass_action_id TEXT,
|
||||
CONSTRAINT fk_operation_id
|
||||
FOREIGN KEY(operation_id) REFERENCES objenious_operation(id)
|
||||
);
|
||||
|
||||
CREATE INDEX operation_change
|
||||
ON objenious_operation_change(operation_id);
|
||||
@@ -11,8 +11,8 @@ post {
|
||||
}
|
||||
|
||||
body:form-urlencoded {
|
||||
iccid: 8933201124059176320
|
||||
offer: SAVEFAMILY1
|
||||
iccid: 8933201125065160422
|
||||
offer: SAVEFAMILY2
|
||||
}
|
||||
|
||||
settings {
|
||||
|
||||
@@ -11,11 +11,11 @@ post {
|
||||
}
|
||||
|
||||
params:query {
|
||||
:
|
||||
~iccid:
|
||||
}
|
||||
|
||||
body:form-urlencoded {
|
||||
iccid: 8933201124059176320
|
||||
iccid: 8933201125065160414
|
||||
}
|
||||
|
||||
settings {
|
||||
|
||||
@@ -26,4 +26,16 @@ export class PgClient {
|
||||
return await this.pgPool.query(text, params);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Función para validar la conexión al inicio.
|
||||
*/
|
||||
public async checkDatabaseConnection(): Promise<void> {
|
||||
const client = await this.pgPool.connect();
|
||||
const res = await client.query('SELECT NOW()');
|
||||
console.log(`[o] Database connected successfully at: ${res.rows[0].now}`);
|
||||
client.release(); // Liberamos el cliente de vuelta al pool
|
||||
return;
|
||||
// Si algo falla se tiene que propagar
|
||||
};
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ export class SimController {
|
||||
|
||||
this.tryUseCase(msg, this.useCases.activate({
|
||||
dueDate: this.genDueDate(2 * 60).toISOString(),
|
||||
customerAccountCode: "9.49411.10", // TODO: Al .env
|
||||
identifier: {
|
||||
identifierType: "ICCID",
|
||||
identifiers: [iccid]
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ActionData, ActivationData } from "#domain/DTOs/objeniousapi.js"
|
||||
import { HttpClient } from "#shared/infrastructure/HTTPClient.js"
|
||||
import { AxiosError } from "axios"
|
||||
import { Result } from "#shared/domain/Result"
|
||||
import { ObjeniousOperation, IOperationsRepository as OperationsRepositoryPort } from "#domain/operationsRepository.port"
|
||||
|
||||
// TODO:
|
||||
// - Pasar a un archivo de DTOs
|
||||
@@ -9,38 +10,54 @@ import { Result } from "#shared/domain/Result"
|
||||
|
||||
|
||||
export class SimUseCases {
|
||||
private httpClient: HttpClient
|
||||
|
||||
private readonly httpClient: HttpClient
|
||||
private readonly operationRepository: OperationsRepositoryPort
|
||||
constructor(args: {
|
||||
|
||||
httpClient: HttpClient
|
||||
httpClient: HttpClient,
|
||||
operationRepository: OperationsRepositoryPort
|
||||
}) {
|
||||
this.httpClient = args.httpClient
|
||||
this.operationRepository = args.operationRepository
|
||||
}
|
||||
|
||||
|
||||
private async logOperation(data: ObjeniousOperation) {
|
||||
await this.operationRepository.createOperation({
|
||||
...data
|
||||
})
|
||||
}
|
||||
|
||||
public activate(activationData: ActivationData): () => Promise<Result<string, boolean>> {
|
||||
const OPERATION_URL = "/actions/activateLine"
|
||||
return async () => {
|
||||
// TODO: validacion de campos
|
||||
|
||||
const req = this.httpClient.client.post(OPERATION_URL, {
|
||||
...activationData
|
||||
})
|
||||
|
||||
|
||||
try {
|
||||
const response = await req
|
||||
console.log("[!] El status de la respuesta es", response.status)
|
||||
|
||||
if (response.status == 200) {
|
||||
console.log("Activacion con exito", response.data.response)
|
||||
|
||||
const operation: ObjeniousOperation = {
|
||||
operation: "activate",
|
||||
iccids: activationData.identifier.identifiers,
|
||||
status: "noMassID"
|
||||
}
|
||||
|
||||
this.logOperation(operation).then(e => {
|
||||
console.log("Logueada operacion", operation)
|
||||
}).catch(e => console.error(e))
|
||||
|
||||
return <Result<string, boolean>>{
|
||||
error: undefined,
|
||||
data: true
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
// muy mejorable el control de errores
|
||||
return {
|
||||
error: String(response.status),
|
||||
data: undefined
|
||||
|
||||
@@ -9,6 +9,7 @@ export type ActionData = {
|
||||
}
|
||||
|
||||
export type ActivationData = ActionData & {
|
||||
customerAccountCode: "9.49411.10" | string,
|
||||
offer: {
|
||||
code: string | "SAVEFAMILY1" | "SAVEFAMILY2",
|
||||
services: any[]
|
||||
|
||||
@@ -5,7 +5,7 @@ export type StatusEnum = 'noRequestID' | 'noMassID' | 'running' | 'finished' | '
|
||||
export interface IOperationsRepository {
|
||||
createOperation(data: ObjeniousOperation): Promise<Result<string, ObjeniousOperation>>
|
||||
updateOperation(data: ObjeniousOperationChange): Promise<Result<string, ObjeniousOperation>>
|
||||
getPendingOerations(): Promise<Result<string, ObjeniousOperation>>
|
||||
getPendingOperations(): Promise<Result<string, ObjeniousOperation[]>>
|
||||
}
|
||||
|
||||
export type ObjeniousOperation = {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
|
||||
import { OperationsRepository } from "#adapters/OperationRepository.js"
|
||||
import { startRMQClient } from "#config/eventBus.config"
|
||||
import { httpInstance } from "#config/httpClient.config"
|
||||
import { pgPool } from "#config/postgreConfig.js"
|
||||
import { PgClient } from "#shared/infrastructure/PgClient.js"
|
||||
import { SimController } from "./aplication/Sim.controller.js"
|
||||
import { SimRouter } from "./aplication/Sim.router.js"
|
||||
import { SimUseCases } from "./aplication/Sim.usecases.js"
|
||||
@@ -8,10 +11,18 @@ import { SimUseCases } from "./aplication/Sim.usecases.js"
|
||||
async function startWorker() {
|
||||
const rmqClient = await startRMQClient()
|
||||
const httpClient = httpInstance
|
||||
|
||||
const pgClient = new PgClient({ pool: pgPool })
|
||||
|
||||
await pgClient.checkDatabaseConnection()
|
||||
|
||||
const operationRepository = new OperationsRepository(pgClient)
|
||||
|
||||
const simActivationController = new SimController(
|
||||
rmqClient,
|
||||
new SimUseCases({
|
||||
httpClient: httpClient
|
||||
httpClient: httpClient,
|
||||
operationRepository: operationRepository
|
||||
})
|
||||
)
|
||||
const simRouter = new SimRouter(simActivationController, rmqClient)
|
||||
|
||||
@@ -13,11 +13,11 @@ export class OperationsRepository implements IOperationsRepository {
|
||||
|
||||
async createOperation(data: ObjeniousOperation): Promise<Result<string, ObjeniousOperation>> {
|
||||
const query = `
|
||||
INSERT INTO objenious_operation (operacion, iccids, status, max_rety)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
INSERT INTO objenious_operation (operation, iccids, status, max_retry, request_id)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
RETURNING *`;
|
||||
const iccids = data.iccids.join(",")
|
||||
const values = [data.operation, data.iccids, data.status, data.max_retry];
|
||||
const values = [data.operation, data.iccids, data.status, data.max_retry, data.request_id];
|
||||
const { rows } = await this.pgClient.query(query, values);
|
||||
return <Result<string, ObjeniousOperation>>{
|
||||
data: rows[0]
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
#/bin/bash
|
||||
rm deployment/database/init.sql
|
||||
cat deployment/database/*.sql >deployment/database/init.sql
|
||||
docker compose -f deployment/local/docker/docker-compose.yaml --project-directory ./ up --watch
|
||||
|
||||
Reference in New Issue
Block a user