Artículo
· 1 abr, 2025 Lectura de 6 min

Conjunto de mensajes huérfanos

En este artículo, hablaremos sobre los Mensajes Huérfanos.

¿Qué es un Mensaje Huérfano?

Cada cuerpo de mensaje está asociado con un encabezado de mensaje que contiene los metadatos. El encabezado incluye información como el nombre de la configuración de origen, el nombre de la configuración de destino, la hora de creación, la hora de procesamiento, la referencia asociada al cuerpo del mensaje, la información de sesión, el nombre de la clase del cuerpo del mensaje y el estado del mensaje.

Cuando existen registros de cuerpos de mensajes que no tienen sus correspondientes registros de encabezado, estos se denominan cuerpos de mensajes huérfanos. En este artículo, analizaremos las posibles causas que pueden generar cuerpos de mensajes huérfanos.

Purgar solo los Encabezados

En la configuración de la tarea de purga, el parámetro BodiesToo determina si se deben purgar también los cuerpos de los mensajes junto con sus encabezados. Si esta opción está desactivada, la tarea de purga eliminará solo los encabezados de los mensajes, dejando los cuerpos de los mensajes intactos. Estos cuerpos de mensajes se convertirán en registros huérfanos, ya que el encabezado de referencia habrá sido eliminado.

Si purgáis los encabezados de los mensajes pero conserváis los cuerpos de los mensajes, el Portal de Gestión no ofrecerá ninguna opción para purgar estos cuerpos de mensajes huérfanos. En este caso, deberéis eliminarlos de forma programada.

(Traducción de la foto de debajo)

Asistente del programador de tareas

Este asistente os ayuda a programar una tarea para su ejecución por el administrador de tareas o a editar los detalles de una tarea previamente programada. Para definir tareas personalizadas, primero debéis crear una nueva subclase de la clase %SYS.Task.Definition, que luego podrá seleccionarse como un "tipo de tarea".

 

Por favor, consultad la documentación sobre la tarea de purga.

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=EGMG_purge#EGMG_purge_basic

Clases Message Body complejas (Propiedades que referencian objetos)

Cuando IRIS purga un cuerpo de mensaje, no necesariamente elimina los objetos referenciados en las propiedades de tipo objeto. Específicamente, elimina otros objetos solo si son objetos serializables o si son objetos secundarios (según una relación definida). Para otros objetos, debéis gestionar su eliminación adecuadamente definiendo un disparador de eliminación o implementando el method %OnDelete() en la body class del mensaje.

Un ejemplo de código para la implementación de OnDelete:

Class Sample.Address Extends %Persistent{
/// The street address.
Property Street As %String(MAXLEN = 80);
/// The city name.
Property City As %String(MAXLEN = 80);
/// The 2-letter state abbreviation.
Property State As %String(MAXLEN = 2);
/// The 5-digit U.S. Zone Improvement Plan (ZIP) code.
Property Zip As %String(MAXLEN = 5);
}
Class Sample.Person Extends %Persistent{
/// Person's name.
Property Name As %String [ Required ];
/// Person's Social Security number. This is validated using pattern match.
Property SSN As %String(PATTERN = "3N1""-""2N1""-""4N") [ Required ];
/// Person's Date of Birth.
Property DOB As %Date;
/// Person's home address.
Property Home As Address;
/// Person's office address.
Property Office As Address;
///Callback for object deletion
ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private ]{
      // Delete the property object references.
      Set tSC = $$$OK, tThis = ##class(Sample.Person).%Open(oid)
      If $ISOBJECT(tThis.Home) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Home.%Id())
      If $ISOBJECT(tThis.Office) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Office.%Id())
      Quit tSC
}
///Callback/Trigger for SQL delete
Trigger OnDelete [ Event = DELETE ]{
      // Delete the property object references. {%%ID} holds the id of the record being deleted.
      Set tID={%%ID}
      Set tThis = ##class(Sample.Person).%OpenId(tID)
      If $ISOBJECT(tThis.Home) Do ##class(Sample.Address).%DeleteId(tThis.Home.%Id())
      If $ISOBJECT(tThis.Office) Do ##class(Sample.Address).%DeleteId(tThis.Office.%Id())
      Quit
}
}

Objetos de tipo Mensaje creados pero nunca enviados a otro host

Cuando un mensaje se envía o reenvía a otro host, IRIS crea un nuevo encabezado de mensaje y asocia el cuerpo de mensaje correspondiente. Si el cuerpo del mensaje/instancia de objeto creada en un Servicio/Proceso de Negocio se guarda en disco/base de datos pero nunca se envía a otro host en producción, no tendrá un encabezado asociado y permanecerá como un Message Body Huérfano. La mejor práctica es no crear un message body a menos que se vaya a reenviar o no llamar al método %Save() en la instancia del objeto (la API SendRequestSync/SendRequestAsync lo guardará antes de poner el mensaje en la cola de configuración de destino). De esta forma, el objeto cuerpo del mensaje no será persistido a menos que se envíe a otro host.

La razón más común de este problema es cuando los desarrolladores:

  • Clonan el cuerpo del mensaje y nunca reenvían el cuerpo del mensaje clonado.
  • Se crean objetos de cuerpo de mensaje en variables de Contexto (BPL) y nunca se reenvían.

Efectos de los Mensajes Huérfanos

Los mensajes huérfanos no serán eliminados por la tarea de purga. Estos mensajes consumirán espacio en disco y, a medida que aumente su número proporcionalmente, el uso del disco incrementará. El espacio en disco no solo provendrá de los datos del cuerpo del mensaje, sino también de cualquier índice/entradas de tabla de búsqueda para cada uno de estos registros de cuerpos de mensaje huérfanos.

Identificación de Mensajes Huérfanos

La existencia de mensajes huérfanos puede identificarse consultando el encabezado y el cuerpo del mensaje. Cada encabezado de mensaje hace referencia al cuerpo de mensaje correspondiente. La referencia al Id del objeto cuerpo de mensaje se almacena en la propiedad MessageBodyId del encabezado y el nombre de la clase del cuerpo del mensaje se almacena en la propiedad MessageBodyClassName del encabezado.

Un ejemplo de consulta para encontrar mensajes huérfanos en la tabla de mensajes HL7:

SELECT HL7.Id  FROM EnsLib_HL7.Message HL7

   LEFT JOIN Ens.MessageHeader hdr

   ON HL7.Id=hdr.MessageBodyId

   WHERE hdr.MessageBodyId IS NULL

La consulta anterior devolverá todos los mensajes HL7 que no tienen sus encabezados correspondientes. La consulta puede modificarse para consultar otros tipos de mensajes simplemente reemplazando el nombre de la tabla del message body.

Purgar Mensajes Huérfanos

El Portal de Gestión no proporciona una forma de purgar los cuerpos de mensajes huérfanos. En este caso, debemos purgar los cuerpos de los mensajes de mediante programación. 

Existe otra rutina escrita como referencia para ayudar a purgar los mensajes huérfanos, pero esta rutina no realiza una purga profunda y solo ayuda a eliminar los cuerpos de los mensajes. He incluido el enlace de GitHub a continuación para descargar el código fuente:

https://gist.github.com/suriyasv/2ed7f2dbcfd8c79f3b9938762c17c0b5

Importante: Esta rutina no se creó específicamente para IRIS (ver artículo original). Debe tomarse simplemente como referencia y ejemplo, pero no debe utilizarse directamente en sistemas en producción.

La mejor práctica es siempre:

  1. Evitar errores de programación (como se mencionó anteriormente) para prevenir mensajes huérfanos.
  2. Configurar la tarea de purga con la opción BodiesToo desactivada solo si es necesario conservar los cuerpos de los mensajes, sabiendo que estos solo podrán purgarse programáticamente.
  3. Implementar relaciones o métodos OnDelete para las propiedades de objetos persistentes.

Espero que este artículo os sea útil al construir vuestra producción. No dudéis en hacernos saber si tenéis preguntas o inquietudes. ¡Gracias!

Comentarios (0)1
Inicie sesión o regístrese para continuar