#Interoperabilidad

0 Seguidores · 127 Publicaciones

En los servicios médicos, la compatibilidad  operativa es la capacidad que tienen los diferentes sistemas en tecnología de la información y aplicaciones de software para comunicarse, intercambiar datos y utilizar la información que se intercambió.

Pregunta Kurro Lopez · oct 21, 2025

Hola comunidad,

Tengo un servicio que utiliza EnsLib.RecordMap.Service.FTPService para capturar ficheros en un directorio FTP.

Necesitaría que en lugar de cargarlos todos a la vez, los hiciera de uno en uno.

Tengo una clase que extiende de esta clase porque hace procesos previos, lo guarda todo en la clase RecordMap y luego los procesa todos los registros a la vez.

Cuando invoco al BP, lo hace a través del método set tStatus = ..SendRequest(message, 1)

He puesto el flag SynchronousSend = 1, pero sigue procesando todos a la vez.

4
0 36
Artículo Jose-Tomas Salvador · oct 23, 2025 10m read

Una novedad que apareció en la versión 2024.1 de InterSystems IRIS for Health y que quizá te pasó desapercibida. Se trata de la capacidad de realizar una validación basada en perfiles FHIR.

 

En este artículo os ofreceré una visión general básica de esta funcionalidad.

Si FHIR es importante para vosotros, deberíais probar sin duda esta nueva característica, así que seguid leyendo.

Contexto

El estándar FHIR define una operación llamada $validate. Esta operación está pensada para ofrecer una API que permita validar recursos.

0
0 18
Artículo Jose-Tomas Salvador · oct 16, 2025 3m read

Para gestionar la acumulación de datos de producción, InterSystems IRIS permite a los usuarios controlar el tamaño de la base de datos purgando periódicamente los datos. Esta purga puede aplicarse a mensajes, registros, procesos de negocio y alertas gestionadas.

Consultad la documentación para obtener más detalles sobre la configuración de la tarea de purga:
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=EGMG_purge#EGMG_purge_settings

0
0 27
Artículo Kurro Lopez · sep 29, 2025 13m read

Estoy muy emocionado de continuar con mi serie de artículos "InterSystems para Dummies", y hoy queremos contarles todo sobre una de las funciones más potentes que tenemos para la interoperabilidad.

Aunque ya las hayan probado, planeamos analizar a fondo cómo sacarles el máximo provecho y mejorar aún más nuestra producción.

¿Qué es Record Mapper?

En esencia, un Record Mapper es una herramienta que permite mapear datos de archivos de texto a mensajes de producción y viceversa. La interfaz del Portal de Administración, por otro lado, permite crear una representación visual de un archivo de texto y un modelo de objeto válido de esos datos para mapearlos a un único objeto de mensaje de producción persistente.

Por lo tanto, si desea importar datos de un archivo CSV a su clase persistente, puede probar con un par de clases entrantes (por FTP o directorio de archivos). ¡Pero no se apresure! Abordaremos cada uno de estos puntos a su debido tiempo.


TIP: Todos los ejemplos y clases descritos en este artículo se pueden descargar desde el siguiente enlace: https://github.com/KurroLopez/iris-recordmap-fordummies.git


¿Cómo empezar?

Vayamos al grano y especifiquemos nuestro escenario.

Necesitamos importar información de nuestros clientes, incluyendo su nombre, fecha de nacimiento, número de identificación nacional, dirección, ciudad y país.

Abra su portal IRIS y seleccione Interoperabilidad – Crear – Record Maps. image

Cree un nuevo Record Maps con el nombre del paquete y la clase. image

En nuestro ejemplo, el nombre del paquete es Demo.Data, mientras que el nombre de la clase es PersonalInfo.

El primer paso es configurar el archivo CSV. Esto significa determinar el carácter separador, si los campos de cadena tienen comillas dobles, etc. image

Si usa el sistema operativo Windows, el terminador de registro común es CRLF (Char(10) Char(12)).

Como mi archivo CSV es estándar, separado por punto y coma (;), debo definir el carácter del separador de campos.

Ahora, voy a declarar los campos del perfil del cliente (nombre, apellidos, fecha de nacimiento, número de identificación nacional, dirección, ciudad y país). image

Esta es una definición básica, pero puedes establecer más condiciones con respecto a tu archivo CSV si lo deseas. image

Recuerda que, por defecto, un campo %String tiene una longitud máxima de 50 caracteres. Por lo tanto, actualizaré este valor para permitir más caracteres en el campo de dirección (un máximo de 100).

También definiré el formato de fecha usando el formato ISO (aaaa-mm-dd), que corresponde al número 3.

Además, haré obligatorios los campos de nombre, apellido y fecha de nacimiento. image

¡Listo! ¡Presionemos el botón "Generar" para crear la clase persistente! image

Let's take a look at the generated class:
/// THIS IS GENERATED CODE. DO NOT EDIT.<br/>
/// RECORDMAP: Generated from RecordMap 'Demo.Data.PersonalInfo'
/// on 2025-07-14 at 08:37:00.646 [2025-07-14 08:37:00.646 UTC]
/// by user SuperUser
Class Demo.Data.PersonalInfo.Record Extends (%Persistent, %XML.Adaptor, Ens.Request, EnsLib.RecordMap.Base) [ Inheritance = right, ProcedureBlock ]
{

Parameter INCLUDETOPFIELDS = 1;

Property Name As %String [ Required ];

Property Surname As %String [ Required ];

Property DateOfBirth As %Date(FORMAT = 3) [ Required ];

Property NationalId As %String;

Property Address As %String(MAXLEN = 100);

Property City As %String;

Property Country As %String;

Parameter RECORDMAPGENERATED = 1;

Storage Default
{
<Data name="RecordDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Name</Value>
</Value>
<Value name="3">
<Value>%Source</Value>
</Value>
<Value name="4">
<Value>DateOfBirth</Value>
</Value>
<Value name="5">
<Value>NationalId</Value>
</Value>
<Value name="6">
<Value>Address</Value>
</Value>
<Value name="7">
<Value>City</Value>
</Value>
<Value name="8">
<Value>Country</Value>
</Value>
<Value name="9">
<Value>Surname</Value>
</Value>
</Data>
<DataLocation>^Demo.Data.PersonalInfo.RecordD</DataLocation>
<DefaultData>RecordDefaultData</DefaultData>
<ExtentSize>2000000</ExtentSize>
<IdLocation>^Demo.Data.PersonalInfo.RecordD</IdLocation>
<IndexLocation>^Demo.Data.PersonalInfo.RecordI</IndexLocation>
<StreamLocation>^Demo.Data.PersonalInfo.RecordS</StreamLocation>
<Type>%Storage.Persistent</Type>
}

}

Como puede ver, cada propiedad tiene el nombre de los campos en nuestro archivo CSV.

En este punto, crearemos un archivo CSV con la siguiente estructura para probar nuestro Record Mapper:

Name;Surname;DateOfBirth;NationalId;Address;City;Country Matthew O.;Wellington;1964-31-07;208-36-1552;1485 Stiles Street;Pittsburgh;USA Deena C.;Nixon;1997-03-03;495-26-8850;1868 Mandan Road;Columbia;USA Florence L.;Guyton;2005-04-10;21 069 835 790;Invalidenstrasse 82;Contwig;Germany Maximilian;Hahn;1945-10-17;92 871 402 258;Boxhagener Str. 97;Hamburg;Germany Amelio;Toledo Zavala;1976-06-07;93789292F;Plaza Mayor, 71;Carbajosa de la Sagrada;Spain

Puedes usarlo como prueba ahora.

Haz clic en "Seleccionar archivo de muestra", selecciona la muestra en /irisrun/repo/Samples y elige PersonalInfo-Test.csv. image

En este momento podrás observar cómo se importan tus datos: image

Los problemas crecen

Justo cuando crees que todo está listo, recibes una nueva especificación de tu jefe:

"Necesitamos los datos para poder cargar el número de teléfono del cliente y almacenar más de uno (fijo, móvil, etc.)".

Uy... Necesito actualizar mi Record Map y agregar un número de teléfono. Sin embargo, debería tener más de uno... ¿Cómo puedo hacerlo?


Nota: Puedes hacerlo directamente en la misma clase. Sin embargo, crearé una nueva para fines explicativos y la guardaré en los ejemplos. De esta manera, puedes revisar y ejecutar el código siguiendo todos los pasos de este artículo.


Bien, es hora de reabrir el Record Map que acabamos de crear.

Agrega el nuevo campo "Phone", pero recuerda indicar que este campo es "Repetido". image

Dado que hemos asignado este campo como "Repetido", debemos definir el carácter separador para los datos replicados. Este indicador se encuentra en el mismo lugar donde normalmente especificamos el separador de campo. image

¡Perfecto! Carguemos el archivo CSV de ejemplo con los números de teléfono separados por #. image

Si echamos un vistazo a la clase persistente que hemos producido, podemos ver que el campo "Phone" es de tipo Lista de %String:

Property Phone As list Of %String(MAXLEN = 20);

Ok, Kurro, pero ¿Cómo podemos subir este archivo?

Es una muy buena pregunta, querido lector.

Intersystems IRIS nos proporciona dos clases de entrada: EnsLib.RecordMap.Service.FileServiceEnsLib.RecordMap.Service.FTPService

No profundizaré en estas clases porque sería demasiado largo. Sin embargo, podemos revisar sus funciones principales.

En resumen, el servicio monitoriza los procesos en una carpeta definida, captura los archivos almacenados en ese directorio, los carga, los lee línea por línea y envía ese registro al proceso de negocio designado.

Esto ocurre tanto en el servidor como en los directorios FTP.

Vayamos al grano…


Nota: Presentaré mis ejemplos utilizando la clase EnsLib.RecordMap.Service.FileService. Sin embargo, la clase EnsLib.RecordMap.Service.FTPService realiza las mismas operaciones.


Si ha descargado el código de ejemplo, verás que se ha creado una producción con dos componentes:

Una clase de servicio (EnsLib.RecordMap.Service.FileService), que cargará los archivos, y una clase de negocio (Demo.BP.ProcessData), que procesará cada uno de los registros leídos del archivo. En este caso, usaremos este último solo para ver los rastros de comunicación.

Es importante configurar algunos parámetros en la clase del Business Service. image

File Path: Es un registro que la clase utiliza para monitorear si hay archivos pendientes de procesamiento. Al colocar un archivo en este directorio, el proceso de carga se activa automáticamente y envía cada registro a la clase definida como Business Process.

File Spec: Es un patrón de archivo para buscar (por defecto, es *, pero podemos definir algunos archivos que deseamos diferenciar de otros procesos). Por ejemplo, podemos tener dos clases de escucha entrantes en el mismo directorio, cada una con una clase RecordMap diferente. Podemos asignar la extensión .pi1 a los archivos que procesará la clase PersonalInfo, mientras que .pi2 marcará los archivos que serán procesados por la clase PersonalInfoPhone.

Archive Path: Es un directorio donde se mueven los archivos después de ser procesados.

Work Path: Es una ruta donde el adaptador debe colocar el archivo de entrada mientras procesa los datos. Esta configuración es útil cuando se usa el mismo nombre de archivo para envíos repetidos. Si no se especifica WorkPath, el adaptador no moverá el archivo durante el procesamiento.

Call Interval: Es la frecuencia (calculada en segundos) de las comprobaciones del adaptador para los archivos de entrada en las ubicaciones especificadas.

RecordMap: Es el nombre de la clase Record Map, que contiene la definición de los datos en el archivo.

Target Config Name: Es el nombre del Proceso de Negocio que maneja los datos almacenados en el archivo.

image

Subdirectory Levels: Es un espacio donde el proceso busca un nuevo archivo. Por ejemplo, si un proceso añade un archivo cada día (lunes, martes, miércoles, jueves y viernes), buscará en todos los subdirectorios, comenzando por el directorio raíz, siempre que especifiquemos el nivel 1. Por defecto, el nivel 0 significa que solo buscará en el directorio raíz.

Delete From Server: Esta función indica que si no se especifica el directorio de los archivos procesados, el archivo se eliminará del directorio raíz.

File Access Timeout: Es un tiempo definido (calculado en segundos) para acceder al archivo. Si el archivo es de solo lectura o hay algún problema que impida el acceso al directorio, se mostrará un error.

Header Count: Es una característica importante que indica el número de encabezados que se deben ignorar. Por ejemplo, si el archivo tiene un encabezado que especifica los campos que contiene, debe indicar cuántas líneas de encabezado contiene para que se puedan ignorar y solo se puedan leer las líneas de datos.

Subir un archivo

Como mencioné anteriormente, el proceso de carga se activa cuando se coloca un archivo en el directorio del proceso.

Nota: Las siguientes instrucciones se basan en el código de ejemplo. En la carpeta "samples", encontrará el archivo PersonalInfoPhone-Test.csv. Debe copiar este archivo a la carpeta del proceso para que se procese automáticamente.


NOTA: Si está trabajando con Docker, use el siguiente comando: docker cp .\PersonalInfoPhone-Test.csv containerId:/opt/irisbuild/process/containerId es el ID de su contenedor, ej: docker cp .\PersonalInfoPhone-Test.csv 66f96b825d43398ba6a1edcb2f02942dc799d09f1b906627e0563b1392a58da1:/opt/irisbuild/process/` image


Para cada registro, lanza una llamada al proceso de negocio con todos los datos. image

¡Excelente trabajo! En tan solo unos pasos, lograste crear un proceso que puede leer archivos de un directorio y administrar esos datos de forma rápida y sencilla. ¿Qué más podrías pedir a tus procesos de interoperabilidad?

Complex Record Map

Nadie quiere tener una vida compleja, pero te prometo que te enamorarás de los Complex Record Map .

Los Complex Record Map son precisamente lo que su nombre indica. Se trata de una combinación de varios Record Maps que nos proporciona información más completa y estructurada.

Imaginemos que nuestro jefe nos contacta y nos plantea los siguientes requisitos:

“Necesitamos información del cliente con más números de teléfono, incluyendo códigos de país y prefijos. También necesitamos más direcciones de contacto, incluyendo códigos postales, países y nombres de estados.

Un cliente puede tener un número de teléfono, dos o ninguno”.

Si necesitamos más información sobre números de teléfono y direcciones, como hemos visto anteriormente, incluir esta información en una sola línea sería demasiado complicado. Separemos las diferentes partes que necesitamos:

  • Información del cliente requerida.
  • Números de teléfono (del 0 al 5).
  • Dirección postal (del 0 al 2).

Para cada sección, crearemos un alias para diferenciar el tipo de información que incluye.

Construyamos cada sección:

Paso 1 Diseña un nuevo Record Maps para la información del cliente (Nombre, Apellidos, Fecha de Nacimiento y Documento Nacional de Identidad) e incluya un identificador para indicar que se trata de la sección USER. image

El nombre de la sección debe ser único para los tipos de datos "USER", ya que son responsables de configurar las columnas y posiciones de cada dato. El contenido debería ser similar al siguiente: USER|Matthew O.;Wellington;1964-07-31;208-36-1552 En NEGRITA, el nombre de la sección, en CURSIVA, el contenido.

Paso 2 Crea las secciones PHONE y ADDRESS para los números de teléfono y las direcciones postales.

Recuerda especificar el nombre de la sección y activar la opción Complez Record Map. imageimage

Ahora deberíamos tener tres clases:

  • Demo.Data.ComplexUser
  • Demo.Data.ComplexPhone
  • Demo.Data.ComplexAddress

Paso 3 Completa el Complex Record Map.

Abre la opción "Complex Record Maps": image

Lo primero que vemos aquí es una estructura con un encabezado y un pie de página. El encabezado puede ser otro mapa de registros para almacenar información del paquete de datos (por ejemplo, información del departamento del usuario, etc.).

Dado que estas secciones son opcionales, las ignoraremos en nuestro ejemplo. image

Establezca el nombre de este registro (por ejemplo, PersonalInfo) y agregue nuevos registros para cada sección. image

Si deseamos que uno de los apartados tenga repeticiones, deberemos indicar los valores mínimos y máximos de repetición. image

De acuerdo a las especificaciones anteriores, el archivo con la información lucirá así:

USER|Matthew O.;Wellington;1964-07-31;208-36-1552
PHONE|1;305;2089160
PHONE|1;805;9473136
ADDR|1485 Stiles Street;Pittsburgh;15286;PA;USA

Si queremos cargar un archivo, necesitamos un servicio que pueda leer este tipo de archivos, e Intersystems IRIS nos proporciona dos clases de entrada para eso:

EnsLib.RecordMap.Service.ComplexBatchFileServiceEnsLib.RecordMap.Service.ComplexBatchFTPService Como mencioné anteriormente, usaremos la clase EnsLib.RecordMap.Service.ComplexBatchFileService como ejemplo. Sin embargo, el proceso para FTP es idéntico.

Utiliza la misma configuración que el Record Map, excepto por el número de línea del encabezado, porque este tipo de archivo no necesita uno: image

Como mencioné anteriormente, el proceso de carga se activa cuando se coloca un archivo en el directorio del proceso.

Nota: Las siguientes instrucciones se basan en el código de ejemplo.

En la carpeta "samples", encontrará el archivo PersonalInfoComplex.txt. Debe copiar este archivo a la carpeta del proceso para que se procese automáticamente.


NOTA: Si trabaja con el ejemplo de Docker, utilice el siguiente comando:

docker cp .\ PersonalInfoComplex.txt containerId:/opt/irisbuild/process/p
containerId es el id de su contenedor, ex: docker cp .\ PersonalInfoComplex.txt 66f96b825d43398ba6a1edcb2f02942dc799d09f1b906627e0563b1392a58da1:/opt/irisbuild/process/

Aquí podemos ver cada fila llamando al Business Service: imageimageimage

Como ya se habrá dado cuenta, los Record Maps son una herramienta potente para importar datos de forma compleja y estructurada. Permiten guardar información en tablas relacionadas o procesar cada dato de forma independiente.

Gracias a esta herramienta, puede crear rápidamente procesos de carga de datos por lotes y almacenarlos sin necesidad de realizar lecturas complejas de datos, separación de campos, validación de tipos de datos, etc.

Espero que este artículo le sea útil.

Nos vemos en el próximo "InterSystems para Dummies".

2
0 33
Artículo Alberto Fuentes · sep 1, 2025 7m read

Las preguntas de atención al cliente pueden abarcar datos estructurados (pedidos, productos 🗃️), conocimiento no estructurado (docs/FAQs 📚) y otros sistemas integrados (actualizaciones de envío 🚚). En este post vamos a construir un agente de IA compacto que cubre los tres—usando:

  • 🧠 Python + smolagents para orquestar el “cerebro” del agente
  • 🧰 InterSystems IRIS para SQL, Búsqueda Semántica (RAG) e Interoperabilidad (una API de seguimiento de envío simulada)

⚡ TL;DR (versión express)

  • Construye un Agente de Atención al Cliente funcional con Python + smolagents orquestando herramientas sobre InterSystems IRIS (SQL, Búsqueda Semántica/RAG, Interoperabilidad con una API simulada).
  • Responde preguntas reales (p. ej., “¿Se entregó el pedido #1001?”“¿Cuál es el plazo de devolución?”) combinando tablas, documentos y llamadas de interoperabilidad.
  • Inicia IRIS en Docker, carga el esquema y datos de ejemplo, prepara los embeddings de los documentos para RAG, registra herramientas (SQL/RAG/API) y ejecuta el agente por línea de comando o interfaz gráfica.

image


🧭 Lo que vas a construir

Un Agente de Atención al Cliente capaz de:

  • 🔎 Consultar datos estructurados (clientes, pedidos, productos, envíos) vía SQL
  • 📚 Recuperar conocimiento no estructurado (FAQs y documentos) con RAG sobre IRIS Vector Search (Búsqueda Vectorial)
  • 🔌 Llamar a una API de seguimiento envío (simulada) mediante el framework de Interoperabilidad de IRIS, con Visual Trace para inspeccionar cada llamada

Arquitectura (resumida)

Usuario ➜ Agente (smolagents CodeAgent)
               ├─ Herramienta SQL ➜ Tablas en IRIS
               ├─ Herramienta RAG ➜ Búsqueda Vectorial en IRIS (embeddings + chunks)
               └─ Herramienta Seguimiento Envío ➜ Interoperabilidad IRIS (simulada) ➜ Visual Trace

¿Conoces smolagents? Es un framework ligero de agentes de Hugging Face en el que el modelo planifica y utiliza tus herramientas; como alternativas, puedes considerar LangGraph y LlamaIndex.


🧱 Prerrequisitos

  • 🐍 Python 3.9+
  • 🐳 Docker para ejecutar IRIS en un contenedor
  • 🧑‍💻 VS Code para revisar el código
  • 🔑 Clave de API de OpenAI (para el LLM y los embeddings) — o ejecútalo localmente con Ollama si lo prefieres

1) 🧩 Clona el repositorio y prepara un entorno Python

git clone https://github.com/intersystems-ib/customer-support-agent-demo
cd customer-support-agent-demo

python -m venv .venv
# macOS/Linux
source .venv/bin/activate
# Windows (PowerShell)
# .venv\Scripts\Activate.ps1

pip install -r requirements.txt
cp .env.example .env   # añade tu clave de OpenAI

2) 🐳 Arranca InterSystems IRIS (Docker)

docker compose build
docker compose up -d

Abre el Management Portal (http://localhost:52773 en esta demo).


3) 🗃️ Carga los datos estructurados (SQL)

Desde el SQL Explorer de IRIS o tu cliente SQL favorito:

LOAD SQL FROM FILE '/app/iris/sql/schema.sql' DIALECT 'IRIS' DELIMITER ';';
LOAD SQL FROM FILE '/app/iris/sql/load_data.sql' DIALECT 'IRIS' DELIMITER ';';

Este es el esquema que acabas de cargar: image

Ejecuta algunas consultas para familiarizarte con los datos. El agente usará estas tablas para resolver preguntas:

-- Listado de clientes
SELECT * FROM Agent_Data.Customers;

-- Pedidos de un cliente
SELECT o.OrderID, o.OrderDate, o.Status, p.Name AS Product
FROM Agent_Data.Orders o
JOIN Agent_Data.Products p ON o.ProductID = p.ProductID
WHERE o.CustomerID = 1;

-- Info de envío de un pedido
SELECT * FROM Agent_Data.Shipments WHERE OrderID = 1001;

✅ Si ves filas, tu parte estructurada está lista.


4) 📚 Añade conocimiento no estructurado con Vector Search (RAG)

Crea una configuración de embeddings (el ejemplo usa un modelo de OpenAI; ajústalo a tu gusto):

INSERT INTO %Embedding.Config
  (Name, Configuration, EmbeddingClass, VectorLength, Description)
VALUES
  ('my-openai-config',
   '{"apiKey":"YOUR_OPENAI_KEY","sslConfig":"llm_ssl","modelName":"text-embedding-3-small"}',
   '%Embedding.OpenAI',
   1536,
   'a small embedding model provided by OpenAI');

¿Quieres los pasos y opciones exactos? Consulta la documentación

Después, genera los embeddings del contenido de ejemplo:

python scripts/embed_sql.py

Comprueba que los embeddings están en las tablas:

SELECT COUNT(*) AS ProductChunks FROM Agent_Data.Products;
SELECT COUNT(*) AS DocChunks     FROM Agent_Data.DocChunks;

🔎 Bonus: Búsqueda híbrida + vectorial directamente desde SQL con EMBEDDING()

Una gran ventaja de IRIS es que puedes hacer búsqueda semántica (vectorial) dentro de SQL y mezclarla con filtros clásicos—sin microservicios extra. La función EMBEDDING() de SQL crea al vuelo el vector de tu texto de búsqueda y puedes compararlo con vectores almacenados usando operaciones como VECTOR_DOT_PRODUCT.

Ejemplo A — Búsqueda híbrida de productos (filtro por precio + ranking semántico):

SELECT TOP 3
    p.ProductID,
    p.Name,
    p.Category,
    p.Price,
    VECTOR_DOT_PRODUCT(p.Embedding, EMBEDDING('headphones with ANC', 'my-openai-config')) score
FROM Agent_Data.Products p
WHERE p.Price < 200
ORDER BY score DESC

Ejemplo B — Búsqueda semántica de fragmentos de documentos (ideal para alimentar RAG):

SELECT TOP 3
    c.ChunkID  AS chunk_id,
    c.DocID      AS doc_id,
    c.Title         AS title,
    SUBSTRING(c.ChunkText, 1, 400) AS snippet,
    VECTOR_DOT_PRODUCT(c.Embedding, EMBEDDING('warranty coverage', 'my-openai-config')) AS score
FROM Agent_Data.DocChunks c
ORDER BY score DESC

¿Por qué es potente? Puedes pre-filtrar por precio, categoría, idioma, tenant, fechas, etc., y luego ordenar por similitud semántica—todo en una sola sentencia SQL.


5) 🔌 Conecta una API de envíos (mock) con Interoperability

El proyecto expone un pequeño endpoint /api/shipping/status a través de la Interoperabilidad de IRIS — perfecto para simular llamadas “del mundo real”:

curl -H "Content-Type: application/json" \
  -X POST \
  -d '{"orderStatus":"Processing","trackingNumber":"DHL7788"}' \
  http://localhost:52773/api/shipping/status

Ahora abre Visual Trace en el Portal para ver el flujo de mensajes paso a paso (como el radar de un aeropuerto ✈️).


6) 🤖 Conoce al agente (smolagents + tools)

Echa un vistazo a estos archivos:

  • agent/customer_support_agent.py — inicia un CodeAgent y registra las herramientas
  • agent/tools/sql_tool.py — utilidades SQL parametrizadas
  • agent/tools/rag_tool.py — búsqueda vectorial + recuperación de documentos
  • agent/tools/shipping_tool.py — llamadas al endpoint de Interoperability

El CodeAgent planifica qué pasos dar y genera código que llama a tus herramientas. Tú pones las herramientas; él pone el cerebro con un modelo LLM.


7) ▶️ Ejecútalo

Modo one-shot (pruebas rápidas)

python -m cli.run --email alice@example.com --message "Where is my order #1001?"
python -m cli.run --email alice@example.com --message "Show electronics that are good for travel"
python -m cli.run --email alice@example.com --message "Was my headphones order delivered, and what’s the return window?"

CLI interactivo

python -m cli.run --email alice@example.com

Web UI (Gradio)

python -m ui.gradio
# open http://localhost:7860

🛠️ ¿Cómo funciona?

Flujo del agente (simplificado):

  1. 🧭 Planifica cómo resolver la pregunta y qué herramientas usar: p. ej., “comprobar estado del pedido → buscar política de devoluciones”.

  2. 🛤️ Llama a las herramientas según se necesite

    • 🗃️ SQL para clientes/pedidos/productos
    • 📚 RAG sobre embeddings para FAQs/docs (recuerda que puedes prototipar RAG directamente en SQL con EMBEDDING() + operaciones vectoriales como arriba)
    • 🔌 Interoperability API para estado de envíos
  3. 🧩 Sintetiza: compone una respuesta clara y precisa.

Añade o cambia herramientas según crezca tu caso de uso: promociones, garantías, inventario, etc.


🎁 Resumen

Ya tienes un Agente de Atención al Cliente compacto que combina:

  • 🧠 Razonamiento LLM (smolagents CodeAgent)
  • 🗃️ Datos estructurados (IRIS SQL)
  • 📚 Conocimiento no estructurado (IRIS Vector Search + RAG) — con el plus de que EMBEDDING() te permite búsqueda híbrida + vectorial directamente desde SQL
  • 🔌 Llamadas a sistemas en vivo (IRIS Interoperability + Visual Trace)
1
1 60
Artículo Ricardo Paiva · jun 4, 2025 3m read

IRIS admite transformaciones CCDA y FHIR de forma nativa, pero acceder y visualizar estas funcionalidades requiere tiempo de configuración y conocimiento del producto. La aplicación IRIS Interop DevTools fue diseñada para cerrar esa brecha, permitiendo a los implementadores comenzar de inmediato y explorar las capacidades de transformación integradas del producto.

Además del entorno de transformación IRIS XML, XPath y CCDA, el paquete Interop DevTools ahora proporciona:

0
0 41
Artículo Landon Minor · mayo 30, 2025 3m read

Perfilando Documentos CCD con la Herramienta CCD Data Profiler de LEAD North
¿Alguna vez has abierto un CCD y te has encontrado con una pared de XML enredada? No estás solo. Aunque los CCD son un formato central para el intercambio de datos clínicos, son notoriamente densos, prolijos y poco amigables para la vista humana. Para los desarrolladores y analistas que intentan validar su estructura o extraer información significativa, navegar estos documentos puede sentirse más como arqueología que como ingeniería.

0
0 49
Artículo Ricardo Paiva · mayo 28, 2025 2m read

Después de que desplegáramos un nuevo contenedor basado en containers.intersystems.com/intersystems/irishealth:2023.1 esta semana, notasteis de repente que el Repositorio FHIR empezó a responder con un Error 500. Esto se debe a violaciones de PROTECT en el nuevo espacio de nombres y base de datos HSSYSLOCALTEMP, utilizado por esta versión de los componentes FHIR de IRIS for Health.

La solución consiste en añadir "%DB_HSSYSLOCALTEMP" a las Aplicaciones Web que gestionan las solicitudes FHIR. Podéis automatizar esto ejecutando el siguiente método de clase en los espacios de nombres que definen estas Aplicaciones Web.

do ##class(HS.HealthConnect.FHIRServer.Upgrade.MethodsV6).AddLOCALTEMPRoleToCSP()

En nuestro caso, eso no fue suficiente. En parte de nuestro código personalizado necesitamos acceder al token Bearer JWT tal como lo envía el cliente, y antes podíamos obtenerlo desde el elemento AdditionalInfo "USER:OAuthToken", que ya no está presente en la versión 2023.6.1.809, como se describe en la siguiente documentación: https://docs.intersystems.com/upgrade/results?product=ifh&versionFrom=2023.1.0&versionTo=2023.1.6&categories=Business%20Intelligence,Cloud,Core,Development%20Tools,Driver%20Technologies,Embedded%20Python,External%20Languages,FHIR,Healthcare%20Interoperability,Interoperability,Machine%20Learning,Mirroring,Monitoring,Natural%20Language%20Processing,SQL,Security,Sharding,Web%20Applications&audience=All&changes=121

Resolvimos este problema añadiendo la siguiente lógica para obtener el token desde la caché de tokens.

	$$$ThrowOnError(##class(HS.HC.Util.InfoCache).GetTokenInfo(pInteropRequest.Request.AdditionalInfo.GetAt("USER:TokenId"), .pTokenInfo))
	set OAuthToken = pTokenInfo("token_string")
0
0 22
InterSystems Official Jose-Tomas Salvador · mayo 27, 2025

Estamos publicando una versión puntual de InterSystems IRIS, IRIS for Health y Health Connect 2025.1 — versión 2025.1.0.225.1 — para abordar un problema crítico de interoperabilidad que afecta a quienes utilizan hosts de negocio con la opción de Configuración Predeterminada del Sistema habilitada.

0
0 25
Artículo Laura Blázquez García · mayo 23, 2025 1m read

 

Os presento FHIRCraft, una herramienta ligera para generar recursos FHIR sintéticos.

Quizás estéis pensando:
“Pero... ¿no existe ya Synthea, que genera un montón de recursos FHIR?”
Exactamente — y por eso mismo creé esta aplicación.

FHIRCraft está diseñada para generar recursos FHIR más simples, pequeños y enfocados. A diferencia de Synthea, no pretende simular historiales clínicos completos ni flujos asistenciales. Está pensada para quienes están empezando con FHIR, quieren hacer pruebas de forma progresiva o explorar cómo funciona un recurso específico en aislamiento.

0
0 44
Artículo Jose-Tomas Salvador · mayo 19, 2025 3m read

Uno de los desafíos al crear un mensaje DICOM es cómo poner los datos en el lugar correcto. Parte de ello es insertar los datos en las etiquetas específicas de DICOM, mientras que la otra parte es insertar datos binarios como una imagen. En este artículo explicaré ambos.

Para crear un mensaje DICOM, podéis usar la clase EnsLib.DICOM.File (para crear un archivo DICOM) o la clase EnsLib.DICOM.Document (para crear un mensaje que se pueda enviar directamente a PACS). En ambos casos, el método SetValueAt os permitirá añadir vuestros datos a las etiquetas DICOM.

0
0 52
Anuncio Sergio Farago · mayo 13, 2025

Hola desarrolladores,

Nos complace anunciar el nuevo concurso de programación en línea de InterSystems dedicado a todo lo relacionado con la salud:

🏆 Concurso de Interoperabilidad de Salud Digital y FHIR de InterSystems 🏆

Duración: 12 de mayo - 1 de junio de 2025

Beca total: $12,000


0
0 34
InterSystems Official Jose-Tomas Salvador · abr 1, 2025 5m read

La interfaz de usuario de Interoperabilidad ahora incluye experiencias modernizadas para las aplicacionesDTL Editory Production Configuration, las cuales están disponibles para su activación en todos los productos de interoperabilidad. Podéis alternar entre las vistas moderna y tradicional. Todas las demás pantallas de interoperabilidad permanecen en la interfaz de usuario estándar. Tenéis que tener en cuenta que los cambios se limitan a estas dos aplicaciones, y a continuación se identifica la funcionalidad que está disponible actualmente.

0
0 44
Artículo Jose-Tomas Salvador · abr 1, 2025 6m read

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.

0
0 39
Artículo Jose-Tomas Salvador · mar 10, 2025 5m read

Hola

Este artículo es el resultado de la pregunta que había hecho a la comunidad: Adaptador UDP no funciona

En este artículo, voy a presentaros

1) ¿Qué es "UDP"?
2) El estado actual de Iris con UDP
3) Mi solución con el adaptador UDP


1) ¿Qué es "UDP"?

UDP significa User Datagram Protocol. Es uno de los protocolos fundamentales del conjunto de protocolos de Internet (IP) y se utiliza para transmitir datos a través de una red. Aquí tenéis algunas características clave de UDP:

0
0 76
Artículo Laura Blázquez García · feb 23, 2025 4m read

Cuando creamos un repositorio FHIR en IRIS, tenemos un endpoint para acceder a la información, crear nuevos recursos, etc. Pero hay algunos recursos en FHIR que probablemente no tengamos en nuestro repositorio, por ejemplo, un recurso Binary (este recurso devuelve un documento, como un PDF, por ejemplo).

He creado un ejemplo en el que cuando se solicita un recurso Binary, el endpoint de FHIR devuelve una respuesta, como si existiera en el repositorio.

0
0 82
Artículo Joel Espinoza · feb 4, 2025 2m read

Estimada comunidad,

Quería comentarles que hoy publique en OpenExchange un acelerador de APIs muy simple de implementar (con algún parecido a Redis, pero más funcional) y con resultados bastante buenos, a continuación está la publicación del README, espero les sea de ayuda!

https://openexchange.intersystems.com/package/memoria

Memoria

Esta aplicación permite almacenar el resultado de una llamada a la API GET de forma permanente o por un periodo de tiempo, reduciendo los tiempos de respuesta al cliente final.

En el ejemplo a continuación se utiliza la API pública de Rick & Morty para realizar varias consultas al servidor. Cada consulta por sí sola y utilizando la conexión a internet del hogar demora alrededor de 300 ms. Al utilizar el acelerador el tiempo de respuesta es de alrededor de 7 ms.

Cliente

La clase memoria.client es la encargada de llamar al método MGet, este método ejecuta la llamada a la API externa pero primero valida si la información de esta API está cacheada en la tabla memoria.store, de ser así valida que esté dentro del Time to Live (TTL) configurado y retorna el dato, si el TTL ya expiró borra la información y genera la llamada, almacena el resultado y lo retorna al programa.

Código de prueba

Para una API estática, es decir, lista de países, nombre de ciudades, etc., recomiendo usar TTL=0 para mantener la lista en la tienda.

Resultado de la API

En la primera llamada (cuadrado rojo en la parte superior), el tiempo de la llamada fue de 722 ms y en todas las demás llamadas, el tiempo fue de aproximadamente 7 ms, en este caso solo un 1 % del tiempo original.

Después de 10 segundos (valor TTL), el tiempo aumentó a 220 ms

Resultado

Panel

El Panel es una pequeña aplicación que le permite administrar los datos almacenados en caché y eliminarlos si es necesario.

Vista del panel

1
0 61
InterSystems Official Jose-Tomas Salvador · ene 22, 2025

¡Tenemos un nuevo curso para ti!... pero sólo si te interesa estar a la última en el mundo de la interoperabilidad en entornos sanitarios. 

Igual no lo sabes, pero la familia de productos de InterSystems, con IRIS for Health y Health Connect a la cabeza, son la tecnología base para gestionar e integrar datos clínicos y administrativos de más de la mitad de la población de España... (por no hablar de EEUU, UK, Paises Bajos,...). Así que, teniendo en cuenta esto, si te dedicas al desarrollo de soluciones  o a la implementación de interfaces o integraciones en el sector salud, este es otro curso que no te puedes perder. Pincha y regístrate. ¡¡No lo dudes!!. Más que nada porque las plazas son limitadas... (ahí lo dejo, que luego me dicen que no lo aviso 😉).

1
0 89
Artículo Jose-Tomas Salvador · ene 22, 2025 1m read

En vuestra Producción de Interoperabilidad, siempre podíais tener una Business Operation (BO) que fuera un cliente HTTP y que utilizara OAuth 2.0 para la autenticación. Sin embargo, teníais que personalizar la BO para esta metodología de autenticación. Desde la versión 2024.3, que se lanzó recientemente, hay una nueva capacidad que proporciona nuevos ajustes para gestionar esto de forma más sencilla.

0
0 56
Artículo Alberto Fuentes · nov 27, 2024 1m read

La capacidad de reenviar mensajes fácilmente siempre ha sido una de las características más destacadas de nuestras capacidades de interoperabilidad.

Con la versión 2024.3 que se lanzará pronto (ya disponible como Developer Preview), ¡lo hemos hecho aún más sencillo!

0
0 71
Artículo Jose-Tomas Salvador · nov 13, 2024 6m read

He estado trabajando en este proceso con algunos compañeros de equipo y pensé que podría ser útil para otros, especialmente si trabajáis con HL7 y Ensemble/HealthConnect/HealthShare y rara vez os aventuráis más allá de la sección de Interoperabilidad.

Primero, me gustaría establecer que este tutorial es una extensión de la documentación ya existente sobre la importación y exportación de datos SQL, que se encuentra aquí: https://docs.intersystems.com/iris20241/csp/docbook/DocBook.UI.Page.cls?KEY=GSQL_impexp#GSQL_impexp_import

0
0 56
Artículo Alberto Fuentes · oct 21, 2024 3m read

¡Muy buenas a todos! Os paso un ejemplo de resolución de problemas a la hora de implementar transformaciones de datos que es muy interesante: estaba trabajando en un transformación de datos (DTL) de mensajes HL7 pero no paraba de obtener errores del tipo ERROR #5002... MAXSTRING. El problema era que la mayor parte de acciones en la interfaz gráfica de DTL utilizan el tipo de datos %String al trabajar con segmentos de un mensaje HL7.

Un %String tiene un límite de 3,641,144 caracteres, y mi OBX5.1 tenía 5,242,952 caracteres de longitud, como en el ejemplo proporcionado. Por supuesto, el administrador del sistema PACS dijo que se necesitaban archivos de ultra alta calidad, incluyendo resolución 4K, por lo que no pudimos lograr que el proveedor comprimiera o reformateara estos archivos a jpg comprimido o algo similar.

Inicialmente, este proveedor envía un ORU^R01 en la versión 2.3, y el EHR espera un MDM^T02 también en la versión 2.3. Además, necesitábamos realizar las siguientes transformaciones:

  1. La imagen incrustada se enviaba en OBX-5.1, y necesitábamos moverla a OBX-5.5.
  2. El formato de la imagen se enviaba en OBX-6, y lo necesitábamos en OBX-5.3 y OBX-5.4.
  3. Necesitábamos crear un segmento TXA.
  4. Soportar un conjunto de 25 segmentos OBX que podían estar completamente vacíos (>25 x 5Mb = ¡más de 125Mb de tamaño de mensaje!).

Ejemplo de estructura de mensaje recibido (cada "..." quedaría reemplazado con datos de más de 5 MB):

MSH|^~\&|VENDOR||||20241017125335||ORU^R01|1|P|2.3|
PID|||203921||LAST^FIRST^^^||19720706|M||||||||||100001|
PV1||X||||||||GI6|||||||||100001|
ORC|RE||21||SC||1|||||||||||
OBR|1||21|21^VENDOR IMAGES|||20241017123056|||||||||1001^GASTROENTEROLOGY^PHYSICIAN|||||Y||||F||1|
OBX|1|PR|100001|ch1_image_001.bmp|...^^^^^^^|BMP|||||F|
OBX|2|PR|100001|ch1_image_003.bmp|...|BMP|||||F|
OBX|3|PR|100001|ch1_video_01thumbnail.bmp|...|BMP|||||F|
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||
OBX||||||||||||

Las herramientas y métodos de prueba habituales no estaban a la altura para manejar mensajes tan grandes. Cuando usaba este ejemplo reemplazando los datos con ..., la interfaz gráfica de DTL de arrastrar y soltar funcionaba bien, pero al insertar los datos reales, todo se venía abajo.

Finalmente, descubrí que tenía que usar un bloque de código con ObjectScript y los tipos de datos Stream para poder trabajar correctamente con estos mensajes grandes.

Comparto mi clase final de DTL para cualquiera que venga después de mí y pueda encontrar esto útil:

Class OrdRes.VendorMDM Extends Ens.DataTransformDTL [ DependsOn = EnsLib.HL7.Message ]
{

Parameter IGNOREMISSINGSOURCE = 1;

Parameter REPORTERRORS = 1;

Parameter TREATEMPTYREPEATINGFIELDASNULL = 0;

XData DTL [ XMLNamespace = "http://www.intersystems.com/dtl" ]
{
<transform sourceClass='EnsLib.HL7.Message' targetClass='EnsLib.HL7.Message' sourceDocType='2.3:ORU_R01' targetDocType='2.5:MDM_T02' create='new' language='objectscript' >
<assign value='source.{MSH}' property='target.{MSH}' action='set' />
<assign value='"MDM"' property='target.{MSH:MessageType.MessageCode}' action='set' />
<assign value='"T02"' property='target.{MSH:MessageType.TriggerEvent}' action='set' />
<assign value='"2.5"' property='target.{MSH:VersionID.VersionID}' action='set' />
<assign value='source.{MSH:DateTimeofMessage}' property='target.{EVN:2}' action='set' />
<assign value='source.{PIDgrpgrp().PIDgrp.PID}' property='target.{PID}' action='set' />
<assign value='source.{PIDgrpgrp().PIDgrp.PV1grp.PV1}' property='target.{PV1}' action='set' />
<assign value='source.{PIDgrpgrp().ORCgrp().ORC}' property='target.{ORCgrp().ORC}' action='set' />
<assign value='source.{PIDgrpgrp().ORCgrp().OBR}' property='target.{ORCgrp().OBR}' action='set' />
<assign value='source.{PIDgrpgrp().ORCgrp().NTE()}' property='target.{ORCgrp().NTE()}' action='set' />
<assign value='"Endoscopy Image"' property='target.{TXA:DocumentType}' action='set' />
<assign value='"AU"' property='target.{TXA:DocumentCompletionStatus}' action='set' />
<assign value='"AV"' property='target.{TXA:DocumentAvailabilityStatus}' action='set' />
<assign value='source.{PID:18}' property='target.{TXA:12.3}' action='set' />
<code>
<![CDATA[
 set OBXCount=source.GetValueAt("PIDgrpgrp(1).ORCgrp(1).OBXgrp(*)")
 For k1 = 1:1:OBXCount
 {
   // if OBX-1 is empty then it is assumed the rest of the segment will be empty too, so disregard it.
   If source.GetValueAt("PIDgrpgrp(1).ORCgrp(1).OBXgrp("_k1_").OBX:SetIDOBX") '= ""
   {
     // create new stream to read source OBX
     set srcOBXStream=##class(%Stream.GlobalCharacter).%New()
     // get stream data from source OBX
     set tSC=source.GetFieldStreamRaw(srcOBXStream,"PIDgrpgrp(1).ORCgrp(1).OBXgrp("_k1_").OBX")
     // get the positions of needed delimitters:
     set p1=srcOBXStream.FindAt(1,"|")    // 0>p1="OBX"
     set p2=srcOBXStream.FindAt(p1+1,"|") // p1>p2=OBX-1
     set p3=srcOBXStream.FindAt(p2+1,"|") // p2>p3=OBX-2
     set p4=srcOBXStream.FindAt(p3+1,"|") // p3>p4=OBX-3
     set p5=srcOBXStream.FindAt(p4+1,"|") // p4>p5=OBX-4
     set p6=srcOBXStream.FindAt(p5+1,"^") // p5>p6=OBX-5.1
     set p7=srcOBXStream.FindAt(p6+1,"|") // p6>p7=OBX-5.2 -> OBX 5.*
     // if no OBX-5.2 then there will not be the `^` and p6 and p7 will be `-1`
     // when that is the case, find p7 starting at `p5+1` and make p6 = p7
     if (p6 < 0) {
       set p7=srcOBXStream.FindAt(p5+1,"|") // p5>p7=OBX-5
       set p6=p7
     }
     set p8=srcOBXStream.FindAt(p7+1,"|") // p7>p8=OBX-6
     set tStream=##class(%Stream.GlobalCharacter).%New()

     // renumber OBX-1 to OBX 
     set tSC=tStream.Write("OBX|"_k1_"|")
     
     // set OBX2-2 to "ED"
     set tSC=tStream.Write("ED|")
     
     // copy source OBX-3 to target OBX-3
     set tSC=srcOBXStream.MoveTo(p3+1)
     set tSC=tStream.Write(srcOBXStream.Read(p4-p3-1))
     set tSC=tStream.Write("|")
     
     // copy source OBX-4 to target OBX-4
     set tSC=srcOBXStream.MoveTo(p4+1)
     set tSC=tStream.Write(srcOBXStream.Read(p5-p4-1))
     
     // copy source OBX-6 to OBX-5.3 & OBX-5.4
     set tSC=srcOBXStream.MoveTo(p7+1)
     set docType=srcOBXStream.Read(p8-p7-1)
     set tSC=tStream.Write("|^^"_docType_"^"_docType_"^")
     
     // copy source OBX-5.1 to target OBX-5.5
     // can only set up to 3,641,144 chars at once, so do while loop...
     set startPos=p5+1
     set remain=p6-p5-1
     // characters to read/write in each loop, max is 3,641,144 since .Write limit is a %String
     set charLimit=3000000
     while remain > 0 {
       set tSC=srcOBXStream.MoveTo(startPos)
       set toRead = charLimit
       if toRead > remain {
         set toRead=remain
       }
       set tSC=tStream.Write(srcOBXStream.Read(toRead))
       set remain=remain-toRead
       set startPos=startPos+toRead
     }
     set tSC=tStream.Write("|")

     set obxSegment=##class(EnsLib.HL7.Segment).%New()
     set obxSegment.SegType="2.5:OBX"
     set tSC=obxSegment.StoreRawDataStream(tStream)
     set tSC=target.setSegmentByPath(obxSegment,"OBXgrp("_k1_").OBX")
   }
 }
]]></code>
</transform>
}

}

Para desarrollar y probar esto, utilicé los plugins de VSCode para InterSystems porque las herramientas de prueba de integración no podían manejar el tamaño del mensaje.

También añadiré que, para enviar HL7 sobre HTTPS a InterConnect de Epic, fue necesario crear una clase HTTP personalizada y enviar el tipo de contenido personalizado x-application/hl7-v2+er7.

0
0 114
Artículo Alberto Fuentes · sep 18, 2024 2m read

¡Hola a todos!

Me alegra anunciaros una nueva versión de iris-datapipe, un framework potente que, acompañado de una interfaz gráfica, te permitirá obtener una visión integral de la ingesta y procesamiento de datos en InterSystems IRIS.

¿Por qué iris-datapipe?

En múltiples proyectos, nos dimos cuenta de que repetíamos un patrón común: ingestión de datos de diversas fuentes, enriquecimiento al combinarlos con otros datos, normalización, aplicación de reglas de validación y, finalmente, la realización de alguna acción u operación sobre estos datos (por ejemplo, almacenarlos o enviarlos a otro sistema).

Si bien siempre hemos utilizado las potentes capacidades de interoperabilidad de InterSystems IRIS para implementar estos proyectos, notábamos la necesidad de una visión más integral y lógica del flujo de datos más allá de los múltiples mensajes individuales entre los componentes de interoperabilidad.

Queríamos poder buscar los datos por conceptos de negocio (por ejemplo, un número de registro o lote) y también disponer de una manera sencilla y unificada de entender qué había sucedido con ellos: si estaban en proceso, si alguna regla de validación falló, si ocurrió un error en la comunicación o si fueron procesados correctamente.

image

Para resolver estos desafíos, nació iris-datapipe. Este framework nos permite definir "pipes" de datos que siguen ese patrón de ingesta y procesamiento, todo ello aprovechando las funcionalidades de interoperabilidad de la plataforma, y reduciendo significativamente el esfuerzo requerido. 😊

¿Cómo empezar?

En los próximos días, publicaré otro artículo donde detallaré el proceso de instalación y cómo comenzar a utilizar iris-datapipe.

Mientras tanto, te invito a explorar algunas de las funcionalidades que puedes probar tú mismo con el QuickStart incluido en la aplicación:

image

image

0
0 101
Artículo Ricardo Paiva · sep 12, 2024 3m read

Samba es el estándar para la interoperabilidad de servicios de archivos entre Linux, Unix, DOS, Windows, OS/2 y otros sistemas operativos. Desde 1992, Samba ha proporcionado servicios de archivos seguros, estables y rápidos para todos los clientes (sistemas operativos y programas) utilizando el protocolo SMB/CIFS. Los administradores de red han utilizado SAMBA para crear carpetas de red compartidas que permiten a los empleados de la empresa crear, editar y visualizar archivos corporativos como si estuvieran en sus ordenadores localmente, aunque estos archivos se encuentren físicamente en un

0
0 205
Artículo Jose-Tomas Salvador · jun 6, 2024 2m read

Al desarrollar una nueva Producción de Interoperabilidad, es bastante natural que los parámetros se añadan inicialmente en la Producción.

Sin embargo, en cuanto queréis mover la Producción de desarrollo a un entorno de prueba o staging, queda claro que algunos parámetros de configuración como Servidores HTTP, direcciones IP y/o puertos necesitan ser cambiados. Para evitar que estos parámetros se sobrescriban durante un redepliegue posterior, es esencial que mováis estos parámetros de la Producción a los Parámetros Predeterminados del Sistema.

Crear Parámetros Predeterminados del Sistema manualmente es posible, pero se vuelve complicado cuando tenéis muchos Componentes de Negocio en vuestra producción. Por lo tanto, @Wietze Drost pidió a @Theo Stolker desarrollar una herramienta que automatice este proceso permitiendo especificar qué parámetros o configuraciones deben crearse como Predeterminadas del Sistema usando una expresión de filtro. Esta expresión puede definirse como ":HTTPServer,SSLConfig", donde " * " significa "para cualquier Nombre de Clase de host". Después de los dos puntos, sigue una lista de parámetros a mover. Así, esta expresión significa "crear o actualizar Parámetros Predeterminados del Sistema para todos los parámetros que se denominen 'HTTPServer' y 'SSLConfig'". Podéis definir múltiples expresiones de filtro separadas por un punto y coma, por ejemplo, ":HTTPServer,SSLConfig;FullClassName2:xxx,yyy".

Basándome en su solicitud, escribí el Método de Clase o Class Method denominado GetSettingsFromProduction, que hace precisamente eso:

ClassMethod GetSettingsFromProduction(production As %String, filter As %String = "", removeFromProduction As %Boolean = 0, updateSettings As %Boolean = 1) As %Status

production - El nombre de la producción, si se deja en blanco se usará el nombre de la producción que se está ejecutando actualmente. filter - Un filtro para seleccionar parámetros, como "*:HTTPServer,SSLConfig". Podéis añadir múltiples filtros separados por ";", y se permite usar nombres de clases específicos. Si el filtro se deja en blanco, se procesarán todos los parámetros. removeFromProduction - Si se establece en 1, los parámetros de configuración seleccionados por el filtro se eliminarán de la producción. updateSettings - Si se establece en 0, los parámetros de configuración no se actualizarán en los Parámetros Predeterminados del Sistema.

Al ejecutarse, se escribirá información sobre las acciones tomadas en la terminal.

¡Vuestras preguntas y comentarios son bienvenidos!

0
0 115