...
CONSIDERACIOENS EN EL USO DE COLAS DE MENSAJES
Actualmente las aplicaciones se disponen en la nube (SAS) y esto trajo nuevos paradigmas de soluciones de arquitectura. Uno de ellos es el desacoplar dichas aplicaciones en pequeños componentes o bloques independientes que puedan ser más fáciles de desarrollar, implementar y a futuro mantener. Obviamente tal arquitectura exige un mecanismo confiable y seguro de comunicación entre los mencionados bloques y sobre todo un mecanismo más flexible que la comunicación interproceso tradicional con las limitaciones que éstas imponen.
El uso de colas de mensajes nos brinda una alternativa válida para implementar la mencionada comunicación, y hasta la coordinación de dichos componentes. Consideremos que la cola de mensajes es un arbitro que rompe el conocimiento o dependencia directa entre las partes ya que ella se ubica en medio siendo lo único que conocen y dependen consumidores y productores de mensajes. Con ello el código de comunicación es menor en cada componente y la comunicación sigue un patrón standard como es el de Publisher-suscriber, o Listener DP, que es una solución probada y adoptada en la industria del software.
...
Una gran ventaja a mencionar es que al ser la cola quien administra los datos, existe una mayor tolerancia a fallas, ya que si algún componente no se encuentra disponible es la misma cola la que realiza la persistencia de los datos y ella misma puede implementarse en un esquema de alta disponibilidad mejorando aun mas la tolerancia a errores.
CONSIDERACIONES PARTICULARES A PROMO
...
Del diagrama se desprende que Promo como productor de la información que él administra (ej: Tarjetas de fidelidad), mientras que al mismo tiempo es un consumidor de la información provista por sistemas externos (ej. Catálogo de marcas).
De esta forma se obtienen todas las ventajas mencionadas en la primer parte del documento donde se elimina la interdependencia entre sistemas, y además el balanceo de carga y escalabilidad se hacen de forma transparente ya que tanto Promo como el sistema externo puede crecer independientemente del otro. Al mismo tiempo la comunicación entre ambos sistemas es administrada por el servidor de colas homogeneizando la misma y eliminando la relación directa y por ende la posibilidad de fallas por no encontrar un componente disponible, o no responder en el tiempo estipulado.
...
Para dar soporte a dicha funcionalidad, se debe configurar en el menú Administración, en la sección Información de configuración, las siguientes entradas:
clave | Tipo de Dato | Descripción |
---|---|---|
rabbitMQ.enabled | Booleano | Propiedad que indica si está habilitado RabbitMQ (true o false). Si se fija en TRUE Promo se conectará al servidor RabbitMQ y quedará en escucha del mismo. Si se fija en false se desconectará del mismo. |
rabbitMQ.endpointName | Alfanumérico | Nombre de la cola de RabbitMQ de la cual se consumirán los mensajes |
rabbitMQ.uri | Alfanumérico | URI de conexión completa RabbitMQ (amqp://<user>:<password>@<host>:<port>/<vhost>) vhost: Opcional en caso de estar definido dentro del server RabbitMQ Este parámetro contiene y excluye a los otros marcados con * |
rabbitMQ.username* | Alfanumérico | Usuario para acceder al RabbitMQ |
rabbitMQ.password* | Alfanumérico | Password para acceder al RabbitMQ |
rabbitMQ.host* | Alfanumérico | Dirección (host) del RabbitMQ server |
rabbitMQ.virtualHost* | Alfanumérico | Virtual Host al RabbitMQ |
rabbitMQ.port* | Numérico | Puerto del server RabbitMQ |
Acorde a la tabla anterior tendremos 2 formas excluyentes de configurar, es decir o se utiliza el parámetro de URI o se utilizan sus componentes por separado.
...
Bloco de código | ||||
---|---|---|---|---|
| ||||
{ "companyId": "<companyId>", "catalog": "<catalogName>", "params": [], "items": [{ "operation": "I", "<fieldName>": "<name>", "<fieldCode>": "<code>" }, { "operation": "U", "<fieldName>": "<name>", "<fieldCode>": "<code>" }, { "operation": "D", "<fieldName>": "<name>", "<fieldCode>": "<code>" }, { "operation": "I", "<fieldName>": "<name>", "<fieldCode>": "<code>" } ] } |
...
Donde:
Propiedad | Tipo de dato | Descripción |
companyId | Alfanumérico | Código de la compañía |
catalog | Alfanumérico | Código que identifica el catalogo (VER TIPOS VALIDOS) |
params | JSON | Opcional. Datos auxiliares a definir los cuales se usaran para utilizar en la importación del catalogo |
items | Array de Json | Son los items a importar del catalogo |
operation | Alfabético | Operación a realizar sobre el registro (I ,U, D) "I" indica que el registro debe insertarse "U" indica que el registro debe actualizarse "D" indica que el registro debe eliminarse "IU" indica que el registro será insertado en caso de no existir o bien actualizado si existe |
<fieldName> | Alfanumérico | campos específicos del catalogo a importar |
Âncora | ||||
---|---|---|---|---|
|
catalog | Descripción |
---|---|
catalogCard | Catálogo de Tarjetas de fidelidad |
catalogBrand | Catálogo de Marcas |
catalogCategory | Catálogo de Categorías |
catalogChannel | Catálogo de Canales |
catalogCreditCampaignCode | Catálogo de Campañas Crediticias |
catalogCustomer | Catálogo de Clientes |
catalogCustomerType | Catálogo de tipos de Clientes |
catalogIdType | Catalogo de tipo de identificador |
catalogDepartment | Catálogo de Departamentos |
catalogEventTransaction | Catálogo de eventos |
catalogEventTransactionType | Catálogo de tipo de eventos |
catalogExtendWarranty | Catálogo de Extensión de Garantías |
catalogFamily | Catálogo de Familia de productos |
catalogFormat | Catálogo de Formatos |
catalogInfoFinancial | Catálogo de información financiera |
catalogItem | Catálogo de productos |
catalogItemStock | Catálogo de Stock de productos |
catalogPaymentBank | Catálogo de pagos Bancarios |
catalogPaymentCode | Catálogo de código de pagos Bancarios |
catalogPaymentPrefix | Catálogo de Prefijos Bancarios |
catalogPaymentType | Catálogo de Tipo de pagos |
catalogProfileCode | Catálogo de Código de Perfil del cliente |
catalogStoreChain | Catálogo de cadena de valor |
catalogStore | Catálogo de tiendas |
catalogSubCategory | Catálogo de subcategoría |
catalogSubZone | Catálogo de subzona |
catalogSupplier | Catálogo de proveedor |
catalogZone | Catálogo de zonas |
catalog<CodeFieldDynamic> | Catálogo dinámico el nombre del mismo se forma con el String catalog concatenado con el código del campo dinámico generado en la consola |
...
Ejemplos de carga de Catálogos
...
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{ "companyId": "napse", "catalog": "catalogEventTransactionType", "params": [], "items": [{ "operation": "I", "code": "bf2019", "name": "Black Friday 2019" } ] } |
...
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{ "companyId": "napse", "catalog": "catalogExtendWarranty", "params": [], "items": [{ "operation": "I", "code": "sonyArg", "category": "lineaBlanca", "creditProduct": "40 por ciento", "profileCustomers": "vip", "store": "dot", "skuWarranty": "WAUKH78EX6A144617", "yearsWarranty": "2 años", "initDate": , "endDate": , "endPrice": 13999 }] } |
...
7. Distribuir el mapa con la promoción para poder evaluar la misma.
...
Promo como Productor
Promo permite el envío de información mediante colas RabbitMQ (función productor). Por defecto esta información es enviada cada 30 minutos (proceso background) al servidor de colas.
...
Para dar soporte a dicha funcionalidad, se debe configurar en el menú Administración, en el sub-menú Información de configuración, las siguientes entradas:
clave | Tipo de Dato | Descripción |
---|---|---|
rabbitMQ.producer.enabled | Booleano | Propiedad que indica si está habilitado RabbitMQ para el posteo de datos (true o false) |
rabbitMQ.promotion.endpointName | Alfanumérico | Nombre de la cola de RabbitMQ para el posteo de promociones, la cual se encargara de recibir los mensajes para el posterior procesamiento por parte del Consumer |
rabbitMQ.limitstatus.endpointName | Alfanumérico | Nombre de la cola de RabbitMQ para el posteo del status de limites, la cual se encargara de recibir los mensajes para el posterior procesamiento por parte del Consumer |
rabbitMQ.enginestatus.endpointName | Alfanumérico | Nombre de la cola de RabbitMQ para el posteo del status de motor y consola. |
rabbitMQ.producer.uri | Alfanumérico | URI de conexión completa RabbitMQ para el posteo de datos (amqp://<user>:<password>@<host>:<port>/<vhost>) vhost: Opcional en caso de estar definido dentro del server RabbitMQ |
rabbitMQ.producer.username | Alfanumérico | Usuario para acceder al RabbitMQ para el posteo de datos |
rabbitMQ.producer.password | Alfanumérico | Password para acceder al RabbitMQ para el posteo de datos |
rabbitMQ.producer.host | Alfanumérico | Dirección (host) del RabbitMQ server para el posteo de datos |
rabbitMQ.producer.virtualHost | Alfanumérico | Virtual Host al RabbitMQ para el posteo de datos |
rabbitMQ.producer.port | Numérico | Puerto del server RabbitMQ para el posteo de datos |
rabbitMQ.promotionsCache.endpointName | Alfanumérico | Nombre de la cola RabbitMQ que recibirá los mensajes referentes al Cache de Promociones. (Ver Cache de Promociones) |
Nuevamente la configuración via URI es excluyente a la configuración por parámetros separados. Entonces tendremos dos configuraciones:
...
Bloco de código | ||
---|---|---|
| ||
{ "_id": "603d02251082e8369081744b", "amount": "0", "amountPrev": "0", "card": { "code": "9900000000000000", "status": "ENABLED", "type": "987" }, "cardAction": "ACTIVATION", "companyId": "napse", "createdAt": "2021-03-01T15:03:01Z", "customerCode": null, "date": "2021-03-01T15:03:01Z", "reason": null, "reasonName": null, "storeCode": null, "terminalCode": null } |
Detalle de los campos:
Campo | Descripción | ||||||
id | Id del registro de limite en Mongo. | ||||||
amount | Monto actual asociado a la tarjeta de fidelidad | ||||||
amountPrev | Monto previo de la tarjerta de fidelidad | ||||||
card {} | Datos asociados a la tarjeta informada
| ||||||
cardAction | Accion asociada al movimiento de tarjeta de fidelidad. | ||||||
companyId | Compañía desde la que se envia el movimiento de la tarjeta de fidelidad. | ||||||
createdAt | Fecha de creacion de la tarjeta de fidelidad. | ||||||
customerCode | Cliente asociado a la tarjeta de fidelidad. | ||||||
date | Fecha del movimiento que se informa de la tarjeta de fidelidad. | ||||||
reason | Código de la razón asociada al movimiento que se informa de la tarjeta de fidelidad. | ||||||
reasonName | Nombre de la razón asociada al movimiento que se informa de la tarjeta de fidelidad. | ||||||
storeCode | Código de la tienda asociada al movimiento que se informa de la tarjeta de fidelidad. | ||||||
terminalCode | Código de la terminal asociada al movimiento que se informa de la tarjeta de fidelidad. |
RabbitMQ – Estado de los limites
...
- rabbitMQ.limitstatus.endpointName >> Nombre de la cola de RabbitMQ para el posteo de datos de tipo LimitStatus (informara movimientos de todos los tipos de limites)
...
Ejemplo del Json que se envía:
Bloco de código | ||
---|---|---|
| ||
{ "_id": "603a36021082e83690816fe0", "promotionId": "603a2fa81082e83690816f81", "benefitId": "603a2fce1082e83690816f88", "promotionCode": null, "promotionName": "limite general", "limitId": "603a2fca1082e83690816f87", "scope": "RETAILER", "period": "UNDEFINED", "maxValue": 10.0, "customerId": "-", "storeId": "-", "numberDays": 0, "nextReset": "2021-02-27T03:00:00Z", "lastReset": "2021-02-27T03:00:00Z", "companyId": "napse", "limitTypeCode": "benefiedProductCount", "description": null, "lastUpdate": "2021-02-27T12:07:30Z", "active": true, "currentValue": 1.0 } |
Detalle de los campos:
Campo | Descripción |
id | Id del registro de limite en Mongo. |
promotionId | Id de la promoción en Mongo. |
benefitId | Id del beneficio en Mongo. |
promotionCode | Código de la promoción. |
promotionName | Nombre de la promoción. |
limitId | Id del límite en Mongo. |
scope | Tipo de limite a contabilizar (CUSTOMER, STORE, RETAILER). |
period | Periodo a contabilizar. |
maxValue | Valor máximo al que podrá llegar el limite definido en la promoción. |
customerId | Cliente asociado al límite. |
storeId | Id de la tienda donde se realizó el movimiento del límite. |
numberDays | Cantidad de días definidos para el periodo a contabilizar. |
nextReset | Próximo reseteo del límite. |
lastReset | Ultimo reseteo realizado al límite. |
limitTypeCode | Código del tipo de limite (benefitAmount, benefiedProductCount, benefitApplicationCount). |
description | descripción ingresada en el límite. |
lastUpdate | Ultima actualización del limite (desde consola a promociones con limite definido). |
active | Indica si el limite está a activo (true) o consumido (false). |
currentValue | Valor actual del límite. |
RabbitMQ – Estado de Motor y Consola
...
El Json de RabbitMQ, contendrá el siguiente formato:
Campo | Ejemplos | Tipo de dato | Detalle |
---|---|---|---|
engineId | "1" | Alfanumérico | Identificador del motor o consola. |
engineName | "ENGINE1" | Alfanumérico | Nombre del motor o consola. |
processDate | "16/03/2021 11:33" | Alfanumérico | Fecha y hora del ping del motor o consola. Formato : "dd/MM/yyyy HH:mm" |
startDate | "2021-03-12T03:00:00Z" | Alfanumérico | Fecha de inicio de vigencia del mapa, dato que se informa para el caso del motor si corresponde. Para consola vacío. Formato: "yyyy-MM-dd'T'HH:mm:ssXX" |
endDate | "2021-04-12T03:00:00Z" | Alfanumérico | Fecha fin de vigencia del mapa, dato que se informa para el caso del motor. Para consola vacío. Formato: "yyyy-MM-dd'T'HH:mm:ssXX" |
keyMap | "napse" | Alfanumérico | Identificador, dato que se informa para el caso del motor. Para consola vacío. |
mapVersion | "2" | Alfanumérico | Versión del mapa,para consola vacio. |
stores | "napse" | Alfanumérico | Tiendas solo para motor,para consola vacio. |
statusMQ | "ONLINE" | Alfanumérico | Estado del motor o consola. Valores posibles:ONLINE ,OFFLINE |
timestamp | "16/03/2021 11:35" | Alfanumérico | Fecha y hora de envío |
isConsole | "false" | Alfanumérico | Identifica si el origen es consola. Si es false indica que es motor |
...
Mensajes: Cache de Promociones
...
Bloco de código | ||||||
---|---|---|---|---|---|---|
| ||||||
{ "promotionCode" : "p003", "promotionName" : "Promo03", "SKU" : "2734", "img": “http://myserverPromo:8080/assets/images/promonavidad.jpg” } |
RabbitMQ- Detalle de Transacciones
La cola de mensaje disponible para recibir el detalle de las transacciones a medida que se van registrando en el sistema es:
rabbitMQ.transaction.endopintName >> Nombre de la cola de RabbitMQ para el posteo de datos de transacciones.
Informações |
---|
El Json de la consola se enviará cuando esté activa y operando (con cada ejecución del proceso). |
El Json de RabbitMQ, contendrá el siguiente formato:
cada vez que se realiza una transaccion, se detalla en la consola:
y en la cola RabbitMq;
http://10.4.201.50:15672/#/queues
...
Gestión de Errores
En el caso de existir registros de posteos a server RabbitMQ con ERROR, se mostrara un aviso (banner) en la cabecera de Promo, indicando de forma general la incidencia.
...