Artículo
Bernardo Linarez · Nov 22 Lectura de 4 min

Streams en trazas de interoperabilidad

Hace algún tiempo, empecé a recibir alertas de consumo excesivo de espacio en el sistema de archivos (filesystem) de un cliente, cuya solución utiliza la capa de interoperabilidad (IRIS / Ensemble) de manera masiva.

Me percaté que las bases de datos que crecían eran las dedicadas a la interoperabilidad, mas no la base de datos operacional de la solución, por tanto había que revisar los mensajes de las diferentes integraciones presentes.

También verifiqué los espacios libres de cada base de datos por si compactar y truncar podrían liberar algún espacio importante, pero no era el caso.

(imagen referencial) https://docs.intersystems.com/irisforhealth20201/csp/docbook/DocBook.UI.Page.cls?KEY=GSA_manage#GSA_manage_databases_info

Procedí a revisar si la tarea (task) core de limpieza de mensajes se encontraba configurada y si se estaba ejecutando. Efectivamente la task se ejecutaba con normalidad, por tanto las integraciones estaba generando muchos mensajes y eventualmente pesados.

Dado que no tenía claridad de la naturaleza de todos los mensajes que circulaban por esa producción, decidí ir por el lado de investigar las globales que ocupaban mas espacio, utilizando el comando ^%GZISE, el cual se ejecuta desde consola del namespace que tenga mapeada la base de datos que estamos analizando.

REPO>Do ^%GSIZE

(imagen referencial) 

Esto me dio una idea directa de que la global ^CacheStream estaba ocupando demasiado espacio comparándola con el tamaño total de la base de datos.

Entonces procedí a mirar algunas definiciones de las clases de mensajería, encontrando ejemplos como estos 

Class Test.GetEntity.Response Extends Ens.Response
{

  Property Return As %GlobalCharacterStream;

  Property StatusCode As %String(MAXLEN = "");  

En varios casos había una propiedad de tipo %GlobalCharacterStream. Sin embargo las clases con este tipo de propiedades tienen una global particular definida en su persistencia, por lo que estos stream (cadenas de texto grandes) deberían estar guardados en su global particular.

 Storage Default
{
....
<StreamLocation>^Test.GetEntity.ResponseS</StreamLocation>
...
}   

Sin embargo, encontré a través de una inspección de la global ^CacheStream, cadenas de texto que deberían estar en las globales dedicadas a stream de sus respectivas clases.

(imagen referencial)

Buscando en la comunidad encontré el siguiente post

https://community.intersystems.com/post/streamlocation-doesnt-seem-affec...

Donde una de las respuestas comenta que cierta sintaxis de asignación, afecta directamente en el comportamiento de persistencia del stream.

En vista de esto, empecé a mirar en el código de los diferentes host respecto de como se interactuaba con los stream, encontrando sintaxis de este estilo:

set pResponse.ResponseJSON = fichaClinica   

En donde la variable fichaClinica es un Stream. Entonces procedí a cambiar esta sintaxis por:

Set tSC = pResponse.ResponseJSON.CopyFrom(fichaClinica)
Quit:$System.Status.IsError(tSC)   

De esta manera, se dejó de acumular tanta información en el ^CacheStream y se empezó a distribuir a sus respectivas globales, y se pudo limpiar dicha global.

Sin embargo, posterior a este análisis, se volvió a notar de un aumento en el consumo de espacio en disco. En efecto, la solución estaba recibiendo muchísimas más peticiones (request) que en el momento anterior (casi el cuádruple). Entonces, directamente fui a investigar las globales particulares, comprobando que habían crecido a un ritmo más acelerado.

Entonces decidí mirar las trazas que generaba la solución, percatándome de una en particular:

(imagen referencial)

En este caso de uso, la propiedad ResponseJSON era un stream que representaba el resumen clínico de un paciente (en formato JSON). Era el stream mas largo de entre los diferentes casos de uso. Los eventos [4] y [5] contenían exactamente el mismo JSON, dado que el Business Process (BP) no realizaba ninguna acción sobre dicho stream, sino que simplemente traspasaba el contenido entre el response del BP hacia el response del Business Operation (BO). Además este JSON se guarda en una tabla de bitácora propia de la solución.

En otras palabras, ¡este stream se guardaba en 3 tablas diferentes!. Este JSON persistía en la tabla del response del BO, luego en el response del BP y finalmente en la bitácora de la propia solución.

Entonces se aplicó un cambio a la lógica de esta parte de la integración. En lugar de traspasar el propio stream, se traspasa un objeto con un puntero lógico a ese stream, para que sea obtenido, sólo en el momento que sea necesario:

Esta lógica se implementó a través de una clase que contuviera el %id y la clase que guarda la stream. De esta manera la información ya no se guarda varias veces, y además se evita mostrar datos clínicos en las trazas de integración.

El cambio permitió un consumo menor de espacio en las trazas.

Espero que esta experiencia les ayude en sus implementaciones

 

10
1 0 0 16
Log in or sign up to continue