#InterSystems IRIS for Health

0 Seguidores · 498 Publicaciones

InterSystems IRIS for Health™ es la primera y única plataforma de datos global diseñada específicamente para desarrollar aplicaciones que permitan a los servicios médicos administrar los datos más importantes del mundo. Incluye poderosas funciones listas para utilizarse: procesamiento y análisis de transacciones, un modelo flexible para la información de los servicios médicos, implementación de soluciones basadas en FHIR, soporte para las normas de compatibilidad operativa entre los servicios médicos, y mucho más. Todas estas funciones permiten que los desarrolladores realicen aplicaciones valiosas y novedosas rápidamente. Obtener más información.

Artículo Ariel Arias · nov 22, 2022 7m read

Disclosure Statement: Sugerencias para relalizar pruebas en ambientes usados para demostraciones o desarrollos, no en ambientes productivos.

Caso de uso: teniendo IAM, lo ejecutamos desde un archivo YML, y necesitamos que se conecte a una Instancia IRIS en seguida, pero IRIS tiene deshabilitado el usuario IAM y la aplicación IAM.

0
1 144
Artículo Alberto Fuentes · jun 15, 2022 2m read

¡Hola desarrolladores! Quería compartir hoy un ejemplo muy interesante por parte de Tani Frankel. Se trata de una aplicación sencilla sobre la utilidad SystemPerfomance.

Repasando nuestra documentación sobre la rutina de monitorización ^SystemPerformance (conocida como ^pButtons en versiones anteriores a IRIS), un cliente me dijo «Entiendo todo esto pero ojalá fuese más simple, más sencillo para definir perfiles y gestionarlos, etc.».

Entonces pensé que sería interesante como ejercicio facilitar una pequeña interfaz para hacer esas tareas más sencillas.

El primer paso era envolver en una API basada en clases la rutina actual de ^SystemPerformance.

1
0 524
InterSystems Official David Reche · nov 4, 2022

InterSystems anuncia que la versión 2022.2 de InterSystems IRIS Data Platform, InterSystems IRIS for HealthHealthShare Health Connect e InterSystems IRIS Studio ya está disponible de manera general (GA).

2022.2 es una versión CD (Continuous Delivery, Entrega Continua). Se han añadido muchas actualizaciones y mejoras en 2022.2, en la gestión de SQL, integración cloud, adaptadores Kafka y JMS, SQL Loader y otras áreas. Ya está disponible el nuevo Columnar Storage, pero aún es una funcionalidad en pruebas.

0
0 90
Artículo Alberto Fuentes · mayo 26, 2022 2m read

¡Hola desarrolladores! ¿habéis tenido que desarrollar alguna integración DICOM alguna vez? Es posible que hayáis buscado ejemplo, o incluso un simulador con el que poder simular ciertas comandos. Aquí os paso un ejemplo que puede seros útil.

DICOM es un protocolo de comunicaciones muy extendido en sanidad en el ámbito de la imagen diagnóstica. Tanto con IRIS For Health como con Health Connect podéis desarrollar integraciones que empleen el protocolo DICOM, aquí tenéis disponible la documentación.

En muchas ocasiones, cuando estamos desarrollando la integración DICOM es muy útil que podamos contar con un simulador que haga las veces de un sistema externo (e.g. un PACS) y podamos probar por completo el circuito a implementar antes de conectarlo con un sistema real.

Aquí os paso un ejemplo que implementa dos ejemplos de integraciones DICOM utilizando IRIS For Health y también el simulador dcm4che.

Los dos circuitos de ejemplo que encontraréis son:

Recepción de un DICOM por TCP que contiene un informe PDF embebido

image

Búsqueda y recepción (Query / retrieve) de imágenes en un PACS

Circuito de búsqueda

image

Circuito de recepción

image

Cualquier aporte será bienvenido! :)

6
0 772
Artículo Ricardo Paiva · jun 4, 2021 4m read

Durante las últimas semanas, el equipo de Solution Architecture (Soluciones de Arquitectura) ha estado trabajando para terminar la carga de trabajo de 2019: esto incluyó la creación del código abierto de la Demostración de Readmisiones que llevó a cabo HIMSS el año pasado, para poder ponerla a disposición de cualquiera que busque una forma interactiva de explorar las herramientas proporcionadas por IRIS.

Durante el proceso de creación del código abierto de la demostración, nos encontramos de inmediato con un error crítico. Los datos subyacentes de los pacientes que se utilizaron para crear la demo no podían utilizarse como parte de un proyecto de código abierto porque no eran propiedad de InterSystems, eran propiedad de nuestro socio Baystate Health.

Nuestro equipo estaba en un pequeño aprieto y tenía que encontrar una forma de sustituir los datos originales por datos sintéticos que pudieran utilizarse, pero manteniendo la "historia" de las demos, o su funcionalidad subyacente, consistente. Dado que la demo muestra cómo IRIS admite el workflow de machine learning de un científico de datos, había un nivel de complejidad añadido porque cualquier dato que utilizáramos tenía que ser lo suficientemente realista como para poder apoyar nuestro modelo de investigación. Después de una breve investigación, Synthea vino a nuestro rescate.

Synthea es un generador de pacientes sintéticos, que modela sus historiales médicos. Es de código abierto. Synthea proporciona datos de alta calidad, realistas, pero no reales, de pacientes; en una variedad de formatos (incluido FHIR), con diferentes niveles de complejidad, cubriendo todos los aspectos de la atención médica. Los datos obtenidos no tienen coste, ni privacidad ni restricciones de seguridad, lo que permite investigar con datos de salud que de otra manera no estarían disponibles, de forma legal o práctica.

Después de una investigación inicial, se eligió Synthea como la herramienta para solucionar nuestro problema de datos. Synthea es una herramienta increíble; sin embargo, un problema que encontramos fue que, para ejecutar el software y obtener los pacientes, teníamos que instalar varias dependencias en nuestros equipos.

  • Java JDK 1.8
  • Gradle Build Tool

Cuando trabajas por tu cuenta, esto generalmente no es un problema, pero como nuestro equipo está formado por varias personas, es importante que todos puedan actualizarse con un nuevo software rápidamente; y la instalación de dependencias puede ser una pesadilla. Tenemos el propósito de que el menor número de personas posible sufra durante los procesos de instalación al integrar un nuevo software en nuestro flujo de trabajo.

Como necesitábamos que cualquier persona de nuestro equipo pudiera realizar actualizaciones en la Demo de readmisiones para poder generar pacientes fácilmente, y no queríamos que todos tuvieran que instalar Gradle en sus equipos, nos apoyamos en Docker e introdujimos el software de Synthea dentro de una imagen de Docker, permitiendo que la imagen se ocupe de las dependencias ambientales subyacentes.

Esto terminó funcionando muy bien para nuestro equipo, ya que nos dimos cuenta de que ser capaz de generar datos de pacientes sintéticos sobre la marcha es probablemente un caso de uso muy común al que se enfrentan nuestros compañeros Ingenieros de ventas, por lo que nuestro equipo quería compartirlo con la Comunidad de Desarrolladores.

Cualquiera puede utilizar la siguiente línea de código para generar rápidamente 5 historiales médicos de pacientes sintéticos en formato FHIR, y dejar los pacientes resultantes en una carpeta de salida en el directorio donde está trabajando actualmente.

docker run --rm -v $PWD/output:/output --name synthea-docker intersystemsdc/irisdemo-base-synthea:version-1.3.4 -p 5
  El código de esta imagen Docker tiene su propio repositorio en Github y se puede encontrar aquí para cualquier persona que quiera echar un vistazo, hacer cambios personalizados, o contribuir: https://github.com/intersystems-community/irisdemo-base-synthea

Ahora estamos realizando actualizaciones para que el proyecto sea compatible con módulos personalizados, de modo que cualquiera que desee agregar una enfermedad a sus pacientes generados pueda hacerlo, si Synthea no la proporciona de forma predeterminada, y se incorporará automáticamente a su imagen.

¿Dónde se usa actualmente?

El proceso actual de creación de la Demo de readmisiones utiliza la imagen irisdemo-base-synthea para generar 5 000 pacientes sintéticos sobre la marcha y cargarlos en nuestro repositorio de datos IRIS relacional, normalizado. Cualquier persona que esté interesada en verificar cómo analizar estos datos de pacientes generados de forma sintética (en formato FHIR), puede consultar la Demo de readmisiones creada recientemente con código abierto. La clase que hay que buscar es: IRISDemo.DataLake.Utils. a partir de la línea 613.

La Demo de readmisiones se puede encontrar aquí: https://github.com/intersystems-community/irisdemo-demo-readmission

1
0 316
InterSystems Official David Reche · oct 31, 2022

Este es el décimo de una serie de lanzamientos que forman parte del programa de versiones de prueba 2022.2 para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor producto.

0
0 103
Artículo Luis Angel Pérez Ramos · oct 28, 2022 8m read

Acceso a Producción Programática

Para editar producciones programáticamente (interfaces) puedes usar una combinación de APIs de Interoperabilidad y consultas SQL.

Namespace actual

Es importante conocer el namespace y la producción en la que estás trabajando.

// Object script 
// El namespace activo se guarda en esta variable
$$$NAMESPACE 
// Imprimir el namespace
Write $$$NAMESPACE
# Python
import iris
# Este método retorna el namespace activo
iris.utils._OriginalNamespace()
# Imprimir el namespace
print(iris.utils._OriginalNamespace())
>>> DEMONSTRACIÓN

Producción activa

También, es importante conocer el nombre de tu producción. Puedes recuperar la producción activa en un namespace usando las siguientes APIs

// ObjectScript
USER>ZN "DEMONSTRATION"
// Obtener la última producción en ejecución
DEMONSTRATION>W ##class(Ens.Director).GetActiveProductionName()
>>> Hospital.HospitalProduction
#  Python
import os
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris
active_production = iris.cls('Ens.Director').GetActiveProductionName()
print(active_production)
>>> Hospital.HospitalProduction

Cómo encontrar elementos en una producción

Puedes usar Objectscript o Python para encontrar elementos activos en la producción

1. Consulta SQL para obtener elementos en producción

SELECT Name FROM Ens_Config.Item Where Production = 'Hospital.HospitalProduction'
-- 
['From_Athena_Multi']
['From_Athena_Multi_Router']
['From_Cerner_ADT']
['From_Cerner_ADT_Router']
['From_Cerner_Orders']
['From_Cerner_Orders_Router']
['From_Dictaphone_Results']
['From_Dictaphone_Results_Router']
['From_Lab_Results']
['From_Lab_Results_Router']
['From_Radiology_Results']
['From_Radiology_Results_Router']
['HS.IHE.XDSb.DocumentSource.Operations']
['HS.IHE.XDSb.Repository.Operations']
['To_Cerner_Results']
['To_Dictaphone']
['To_Intellilab']
['To_Lab']
['To_Radiology']
-- 

2. Consulta SQL para obtener elementos activos en producción

SELECT Name, ClassName 
FROM Ens_Config.Item 
WHERE Production = 'Hospital.HospitalProduction' 
  AND Enabled = 1

-- 
Name	                                ClassName
To_Radiology	                        EnsLib.HL7.Operation.FileOperation
To_Lab	                                EnsLib.HL7.Operation.FileOperation
To_Dictaphone	                        EnsLib.HL7.Operation.FileOperation
From_Cerner_ADT	                        EnsLib.HL7.Service.FileService
From_Cerner_ADT_Router	                EnsLib.HL7.MsgRouter.RoutingEngine
From_Radiology_Results_Router	        EnsLib.HL7.MsgRouter.RoutingEngine
From_Lab_Results_Router	                EnsLib.HL7.MsgRouter.RoutingEngine
From_Dictaphone_Results_Router	        EnsLib.HL7.MsgRouter.RoutingEngine
To_Intellilab	                        EnsLib.HL7.Operation.FileOperation
To_Cerner_Results	                    EnsLib.HL7.Operation.FileOperation
From_Cerner_Orders_Router	            EnsLib.HL7.MsgRouter.RoutingEngine
From_Athena_Multi_Router	            EnsLib.HL7.MsgRouter.RoutingEngine
HS.IHE.XDSb.DocumentSource.Operations	HS.IHE.XDSb.DocumentSource.Operations
-- 

3. Acceso por ObjectScript a elementos de la Producción

// ObjectScript 
// Acceso para obtener todos los elementos de una producción activa
// Devuelve la lista de elementos
ClassMethod ListItemsInProduction()
{
    Set productionName =  ##class(Ens.Director).GetActiveProductionName()
    Set items = []
    &sql(Declare curr cursor FOR Select Name into :newId from Ens_Config.Item Where Production = :productionName)
    &sql(OPEN curr)
    For {
        &sql(FETCH curr)
        Quit:SQLCODE
        Do items.%Push(newId)
    }
    &sql(CLOSE curr)
    quit items
}

>>> zw ##class(ISC.SE.ProductionTools).ListItemsInProduction()

["From_Athena_Multi","From_Athena_Multi_Router","From_Cerner_ADT","From_Cerner_ADT_Router","From_Cerner_Orders","From_Cerner_Orders_Router","From_Dictaphone_Results","From_Dictaphone_Results_Router"
,"From_Lab_Results","From_Lab_Results_Router","From_Radiology_Results","From_Radiology_Results_Router","HS.IHE.XDSb.DocumentSource.Operations","HS.IHE.XDSb.Repository.Operations","To_Cerner_Results"
,"To_Dictaphone","To_Intellilab","To_Lab","To_Radiology"]  ; <DYNAMIC ARRAY>
# Python
# Obtención del entorno de datos de los elementos activos de la producción

import os
# Definición de variables de entorno
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris

def getActiveProductionItems():
    productionName = iris.cls('Ens.Director').GetActiveProductionName()
    df = iris.sql.exec("SELECT Name FROM Ens_Config.Item Where Production = '{}'".format(productionName))
    return df

production_items_df = getActiveProductionItems().dataframe()

#                                      name
# 0                       From_Athena_Multi
# 1                From_Athena_Multi_Router
# 2                         From_Cerner_ADT
# 3                  From_Cerner_ADT_Router
# 4                      From_Cerner_Orders
# 5               From_Cerner_Orders_Router
# 6                 From_Dictaphone_Results
# 7          From_Dictaphone_Results_Router
# 8                        From_Lab_Results
# 9                 From_Lab_Results_Router
# 10                 From_Radiology_Results
# 11          From_Radiology_Results_Router
# 12  HS.IHE.XDSb.DocumentSource.Operations
# 13      HS.IHE.XDSb.Repository.Operations
# 14                      To_Cerner_Results
# 15                          To_Dictaphone
# 16                          To_Intellilab
# 17                                 To_Lab
# 18                           To_Radiology

Cómo manipular producciones vía API

1. Añadir componentes

// ObjectScript
set productionName = ##class(Ens.Director).GetActiveProductionName()
//crear un nuevo servicio de archivos xml
set classname="EnsLib.XML.FileService"	//clase de este elemento
set name="NewService"			//nombre de la configuración
set item=##class(Ens.Config.Item).%New(classname)

set item.Name=name
set item.Comment = "Test Service"
set item.PoolSize = "1"
set item.Enabled = 1
do item.%Save()
//	
// Abrir la clase de la producción
// set prod="Test.configtest"	//el nombre de la producción se define manualmente
// O
set prod = productionName
set prodObj=##class(Ens.Config.Production).%OpenId(prod)
//se graba el nuevo elemento
set tSC=prodObj.Items.Insert(item)
set tSC=prodObj.SaveToClass(item)
set tSC=prodObj.%Save()

// ELIMINACIÓN del elemento anterior
set tSC = prodObj.RemoveItem(item)
set tSC = prodObj.SaveToClass()
set tSC=prodObj.%Save()
# Python
import os
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris
active_production = iris.cls('Ens.Director').GetActiveProductionName()
print("Current Production {}".format(active_production))

# Metadata sobre el componente
classname="EnsLib.XML.FileService"	 # clase de esta elemento
name="NewService"			         # nombre de la configuración
item=iris.cls('Ens.Config.Item')._New(classname) # Creación del nuevo componente
item.Name=name
item.Comment = "Test Service"
item.PoolSize = "1"
item.Enabled = 1
item._Save()

# Se carga la clase de la producción
# prod="Test.configtest"	# el nombre de la producción se define manualmente
# O se usa la producción activa anterior
prod = active_production

prodObj=iris.cls('Ens.Config.Production')._OpenId(prod)
# grabamos la producción después de insertar el elemento en ella
tSC=prodObj.Items.Insert(item)
tSC=prodObj.SaveToClass(item)
tSC=prodObj._Save()

# ELIMINAMOS el elemento anterior
tSC = prodObj.RemoveItem(item)
tSC = prodObj.SaveToClass()
tSC=prodObj._Save()

2. Deshabilitar / Habilitar Componentes

// ObjectScript
set productionName = ##class(Ens.Director).GetActiveProductionName()
set itemName = "My.Inbound.HL7"
// Obligatorio para habilitar el elemento
Set componentName = productionName _ "||" _ itemName _ "|"
// Habilitar or deshabilitar
Set enable = 1 // or 0
Do ##class(Ens.Director).EnableConfigItem(componentName, enable, 1)

/// Habilitar o deshabilitar un ConfigItem en una producción. La producción puede estar activa o no.
/// El argumento pConfigItemName proporciona el nombre del elemento de configuración para habilitar o deshabilitar
/// En el caso de múltiples coincidencias de elementos con el mismo nombre de configuración, si alguno ya está habilitado entonces
///  la opción pEnable=1 no hará nada y la opción pEnable=0 deshabilitará el elemento de la producción activa o, si no está activa, 
/// el primer elemento coincidente que esté habilitado que encuentre.
///   
/// Ver el método Ens.Director.ParseConfigName() para ver la sintáxis del string de especificación del nombre del ConfigItem.
ClassMethod EnableConfigItem(pConfigItemName As %String, pEnable As %Boolean = 1, pDoUpdate As %Boolean = 1)
# Python
import os
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris

active_production = iris.cls('Ens.Director').GetActiveProductionName()
item_name = "My.Inbound.HL7"
componentName = active_production + "||" + item_name + "|"

enable = 1 # or 0
iris.cls('Ens.Director').EnableConfigItem(componentName, enable, 1)

Estado de la producción a través de API

// ObjectScript
/// Este método devuelve el estado de la producción por los parámetros de salida.
/// pProductionName: Devuelve el nombre de la producción cuando el estado es en ejecución, suspendida o con problemas.
/// pState: Salidas del estado de la producción. Los valores válidos son:
///          $$$eProductionStateRunning == 1
///          $$$eProductionStateStopped == 2
///          $$$eProductionStateSuspended == 3
///          $$$eProductionStateTroubled == 4
Set sc = ##class(Ens.Director).GetProductionStatus(.productionName, .productionState) 
Write productionName, " -- ", productionState
import os
# Configurar el namespace a las malas
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'

import iris

# TEST 2 con variables de salida
productionName, productionState = iris.ref('productionName'), iris.ref('productionState')
status = iris.cls('Ens.Director').GetProductionStatus(productionName, productionState) 

print("Status: {}".format(status))
# ver .value
print("Production: {}".format(productionName.value))
# ver .value
print("Production State: {}".format(productionState.value))
0
1 169
Artículo Alberto Fuentes · abr 15, 2021 4m read

Hola a todos! Comentamos hoy una entrada de Timothy Leavitt cuyo equipo (Application Services en InterSystems - encargado de desarrollar y mantener muchas de nuestras aplicaciones internas, y proporcionar herramientas y prácticas recomendadas a otras aplicaciones departamentales), durante el último año, se embarcó en un viaje hacia el desarrollo de interfaces de usuario basadas en Angular/REST, para las aplicaciones existentes construidas originalmente con CSP y/o Zen. Esto ha planteado un interesante reto, que os puede resultar familiar a muchos de vosotros: desarrollar nuevas APIs REST para los modelos de datos y la lógica empresarial existentes.

Como parte de este proceso, creamos un nuevo framework para las APIs REST, que ha sido muy útil para nosotros mismos. Ya está disponible en Open Exchange en https://openexchange.intersystems.com/package/apps-rest. Creo que habrá más artículos sobre esto próximamente pero, mientras tanto, hay buenos tutoriales en la documentación del proyecto en GitHub (https://github.com/intersystems/apps-rest).

Como introducción, aquí se encuentran algunos de nuestros objetivos e intenciones de diseño. Todavía no se han realizado todos, ¡pero vamos por buen camino!

Desarrollo y despliegue rápidos

Nuestro enfoque REST debería proporcionar el mismo inicio rápido para el desarrollo de aplicaciones que Zen, ya que resuelve problemas comunes y al mismo tiempo proporciona flexibilidad para los casos de uso específicos de las aplicaciones.

  • Exponer un nuevo recurso para el acceso a REST debería ser tan fácil como exponerlo a un DataModel de Zen.
  • La incorporación/modificación de recursos REST debería involucrar cambios en el nivel al que se accede.
  • La exposición de una clase persistente a través de REST debería llevarse a cabo por herencia y sobre-escrituras de métodos mínimos, pero también debería haber soporte para las funcionalidades equivalentes de programación manual (esto es similar a %ZEN.DataModel.Adaptor y a %ZEN.DataModel.ObjectDataModel).
  • Los patrones comunes de gestión/notificación de errores, serialización/deserialización, validación, etc., no deberían necesitar ser re-implementados para cada recurso en cada aplicación.
  • El soporte para las consultas, el filtrado y la clasificación de los datos de SQL, así como las funciones de búsqueda avanzada y la paginación, deberían estar incorporadas, en vez de que se vuelvan a implementar para cada aplicación.
  • Debería ser fácil desarrollar APIs REST para los métodos de clase y consultas de clase de la API/librería existente, así como a nivel de objeto (CRUD).

Seguridad

La seguridad es una decisión tomada en consecuencia en el momento de diseñar/implementar en vez de una idea de última hora.

  • Cuando las capacidades REST se obtienen por herencia de clases, el comportamiento por defecto debería ser NO proporcionar acceso al recurso, hasta que el desarrollador especifique activamente quién debe recibir acceso y bajo qué condiciones.
  • Las implementaciones estandarizadas de las funciones relacionadas con SQL minimizan la superficie potencial para los ataques de inyección SQL.
  • El diseño debe tener en cuenta el top 10 de la API OWASP (consulta: https://owasp.org/www-project-api-security)

Mantenimiento

La uniformidad del diseño de aplicaciones es una poderosa herramienta para el ecosistema de aplicaciones en una empresa.

  • En vez de acumular un conjunto de API REST de diversa índole e implementaciones programadas de forma manual, deberíamos tener APIs REST de aspecto similar en toda nuestra cartera. Esta uniformidad debería llevar a:
    • Técnicas de depuración comunes.
    • Técnicas de prueba comunes.
    • Técnicas comunes de interfaz de usuario para conectarse a las APIs REST.
    • Facilidad para desarrollar aplicaciones compuestas que accedan a varias APIs.
  • El conjunto de endpoints y el formato de las representaciones de objetos proporcionadas/aceptadas por medio de REST debería estar bien definido, de manera que podamos generar automáticamente la documentación de la API (por ejemplo, Swagger/OpenAPI) basada en estos endpoints.
  • Con base en la documentación estándar de la API, deberíamos ser capaces de generar partes del código del cliente (por ejemplo, clases de typescript correspondientes a nuestras representaciones REST) con la ayuda de herramientas de terceros/estándares de la industria.
2
0 214
InterSystems Official David Reche · oct 21, 2022

Este es el noveno de una serie de lanzamientos que forman parte del programa de versiones de prueba 2022.2 para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor producto.

0
0 76
InterSystems Official David Reche · sep 30, 2022

Este es el octavo de una serie de lanzamientos que forman parte del programa de versiones de prueba 2022.2 para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Se han añadido muchas actualizaciones y mejoras en 2022.2, en la gestión de SQL, integración cloud, adaptadores Kafka y JMS, SQL Loader y otras áreas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor producto

0
0 118
Artículo Ricardo Paiva · sep 29, 2022 2m read

¡Hola Comunidad!

A lo largo de los años siempre he pensado en crear cosas nuevas, modificar las existentes, experimentar, probar, romper (siempre pasa), construir de nuevo, y empezar otra vez.

Los concursos promovidos por InterSystems son una excelente fuente de motivación. Obviamente los premios llaman la atención y eso no se puede negar. Pero no se trata solo de los premios/regalos - los concursos son un reto creativo, una oportunidad de crear, reimaginar, probar, experimentar... Y lo mejor de todo es que eres libre de hacer todo lo que quieras!

Así que ví estos concursos como una oportunidad de crear mi propio Y si...? (la serie en la que Marvel permite a los autores re-imaginar sus historias como quieran) y he sido muy afortunado de encontrar otra persona que recibe estas ideas con los brazos abiertos laugh ¡Muchas gracias, @José Pereira!

En el último concurso de Interoperabilidad, creé el visualizador de mensajes Message Viewer y en este concurso de Interoperabilidad traigo de nuevo el Message Viewer, pero esta vez con Visual Trace!

0
0 152
Artículo Luis Angel Pérez Ramos · sep 29, 2022 2m read

Como sabéis, el namespace EnsDemo de Ensemble ya no está disponible en IRIS.

Esto es algo positivo, ya que IRIS está orientada a la nube y por lo tanto debe ser lo más ligera y rápida posible. La nueva forma de compartir ejemplos de código o módulos es a través de git, integración continua y OpenExchange.

Pero no os preocupéis, somos conscientes de que, en algunos casos, querréis volver a recuperar ejemplos y código presente en EnsDemo, ya sea como fuente de inspiración o para ayudaros a revisar buenas prácticas.

0
0 157
Artículo Ricardo Paiva · sep 22, 2022 5m read

¡Hola Comunidad!

Durante años he trabajado en muchos proyectos diferentes y he podido encontrar muchos datos interesantes.

Pero la mayoría de las veces el conjunto de datos con el que trabajaba era de los clientes. Cuando hace un par de años empecé a participar en los Concursos de Programación de InterSystems, comencé a buscar conjuntos de datos web específicos.

Yo mismo he ido seleccionando algunos datos, pero he pensado: "¿Este conjunto de datos es suficiente para ayudar a otras personas?"

Y discutiendo estas ideas con @José Pereira, decidimos enfocar este tema usando una perspectiva diferente.

Pensamos en ofrecer una variedad de conjuntos de datos que provengan de dos famosas fuentes de datos. De este modo, podemos facilitar que los usuarios encuentren e instalen el conjunto de datos que quieran, de forma rápida y sencilla.

Socrata

La API de datos abiertos de Socrata permite acceder mediante programación a una gran cantidad de recursos de datos abiertos de gobiernos, organizaciones sin ánimo de lucro y ONGs de todo el mundo.

Para esta versión inicial, utilizamos las API de Socrata para buscar y descargar un conjunto de datos específicos.

Abre la herramienta de la API de tu preferencia, como Postman, Hoppscotch

GET> https://api.us.socrata.com/api/catalog/v1?only=dataset&q=healthcare

Este EndPoint devolverá todos los conjuntos de datos relacionados con la atención sanitaria, como en la siguiente imagen: Conjunto de datos de devolución de Socrata

Ahora, consigue el ID. En este caso el ID es: "n9tp-i3k3"

Ve al terminal

IRISAPP>set api = ##class(dc.dataset.importer.service.socrata.SocrataApi).%New()

IRISAPP>do api.InstallDataset({"datasetId": "n9tp-i3k3", "verbose":true})

Compilation started on 01/07/2022 01:01:28 with qualifiers 'cuk'
Compiling class dc.dataset.imported.DsCommunityHealthcareCenters
Compiling table dc_dataset_imported.DsCommunityHealthcareCenters
Compiling routine dc.dataset.imported.DsCommunityHealthcareCenters.1
Compilation finished successfully in 0.108s.

Class name: dc.dataset.imported.DsCommunityHealthcareCenters
Header: Name VARCHAR(250),Description VARCHAR(250),Location VARCHAR(250),Phone_Number VARCHAR(250),geom VARCHAR(250)
Records imported: 26

Después del comando anterior, tu conjunto de datos estará listo para utilizarse!

Conjunto de datos de devolución de Socrata

Kaggle

Kaggle, una filial de Google LLC, es una comunidad en línea de científicos de datos y profesionales del Machine Learning. Kaggle permite que los usuarios encuentren y publiquen conjuntos de datos, exploren y construyan modelos en un entorno de ciencia de datos basados en la web, trabajen con otros científicos de datos e ingenieros de Machine Learning y participen en competiciones para resolver retos de la ciencia de datos.

En junio de 2017 Kaggle anunció que había superado el millón de usuarios registrados, o Kagglers, y desde 2021 cuenta con más de 8 millones de usuarios registrados. La comunidad abarca 194 países. Se trata de una comunidad diversa, que va desde los que acaban de empezar hasta muchos de los investigadores más conocidos del mundo.

Esto es lo que yo llamo una gran comunidad, ¡¿cierto?!

Para utilizar los conjuntos de datos de Kaggle, hay que registrarse en su página web. Después, hay que crear un token de API para utilizar la API de Kaggle.

Creación de tokens de Kaggle

Ahora, igual que con Socrata, puedes utilizar la API para buscar y descargar el conjunto de datos.

GET> https://www.kaggle.com/api/v1/datasets/list?search=appointments

Conjunto de datos de devolución de Kaggle

Ahora, obtén el valor de la referencia. En este caso, la referencia es: "joniarroba/noshowappointments"

Los parámetros de abajo "your-username" y "your-password" son los parámetros que proporciona Kaggle cuando creas el token de API.

IRISAPP>Set crendtials = ##class(dc.dataset.importer.service.CredentialsService).%New()

IRISAPP>Do crendtials.SaveCredentials("kaggle", "<your-username>", "<your-password>")

IRISAPP>Set api = ##class(dc.dataset.importer.service.kaggle.KaggleApi).%New()

IRISAPP>Do api.InstallDataset({"datasetId":"joniarroba/noshowappointments", "credentials":"kaggle", "verbose":true})

Class name: dc.dataset.imported.DsNoshowappointments
Header: PatientId INTEGER,AppointmentID INTEGER,Gender VARCHAR(250),ScheduledDay DATE,AppointmentDay DATE,Age INTEGER,Neighbourhood VARCHAR(250),Scholarship INTEGER,Hipertension INTEGER,Diabetes INTEGER,Alcoholism INTEGER,Handcap INTEGER,SMS_received INTEGER,No-show VARCHAR(250)
Records imported: 259

Después del comando anterior, tu conjunto de datos estará listo para utilizarse!

Selección de Kaggle

Interfaz gráfica de usuario

Para facilitar las cosas, ofrecemos una Interfaz gráfica de usuario para instalar el conjunto de datos. Pero esto es algo que nos gustaría discutir en nuestro próximo artículo. Mientras tanto, a continuación puedes ver un adelanto mientras pulimos algunas cosas antes del lanzamiento oficial:

Lista de conjuntos de datos de Socrata

Conjunto de datos de devolución de Socrata

Video de demostración

¿Cómo es el funcionamiento para descargar un conjunto de datos más grande? +¡¿Más de 400,000 registros no son suficientes?! ¡¿Qué tal 1 MILLÓN DE REGISTROS?! ¡Vamos a verlo!

<iframe width="560" height="315" src="https://www.youtube.com/embed/0T8wXRsaJso" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Voting

0
1 117
InterSystems Official David Reche · sep 16, 2022

Este es el séptimo de una serie de lanzamientos que forman parte del programa de versiones de prueba 2022.2 para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Se han añadido muchas actualizaciones y mejoras en 2022.2, en la gestión de SQL, integración cloud, adaptadores Kafka y JMS, SQL Loader y otras áreas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor producto.

0
0 119
InterSystems Official David Reche · sep 12, 2022

Además de las nuevas plataformas soportadas (Ubuntu 22.04 LTS y RHEL 9), los límites de la "Community Edition" pronto serán actualizados a:

  • Núcleos máximos: 20
  • Conexiones máximas: 8 

NOTA: Estos límites aún no están disponibles para la última versión de prueba 2022.2.0.322.0. Se espera para la versión de prueba 7, que saldrá esta semana.

0
0 92
InterSystems Official David Reche · sep 9, 2022

Este es el sexto de una serie de lanzamientos que forman parte del programa de versiones de prueba 2022.2 para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Se han añadido muchas actualizaciones y mejoras en 2022.2, en la gestión de SQL, integración cloud, adaptadores Kafka y JMS, SQL Loader y otras áreas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor producto.

0
0 118
InterSystems Official David Reche · sep 1, 2022

Este es el quinto de una serie de lanzamientos que forman parte del programa de versiones de prueba 2022.2 para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Se han añadido muchas actualizaciones y mejoras en 2022.2, en la gestión de SQL, integración cloud, adaptadores Kafka y JMS, SQL Loader y otras áreas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor producto.

0
0 93
Artículo Alberto Fuentes · sep 1, 2022 2m read

¡Hola desarrolladores!

Quizá os hayáis encontrado con escenarios donde no tenéis que implementar un repositorio FHIR, sino por ejemplo reenviar peticiones FHIR, gestionar las respuestas y tal vez realizar modificaciones o extraer algunos valores por el camino. Aquí encontraréis algunos ejemplos que pueden implementarse con InterSystems IRIS For Health o HealthShare Health Connect.

En estos ejemplos he utilizado producciones de interoperabilidad con el FHIR Interoperability Adapter y los mensajes tipo HS.FHIRServer.Interop.Request.

Si por el contrario estáis interesados en implementar un repositorio FHIR, no dejéis de ver el Webinar que hicimos en su día.

Un primer escenario podría ser tener que construir una petición FHIR de cero quizá a partir de un fichero o tal vez una consulta SQL y a continuación reenviarlo a un servicio FHIR externo: image

Otro escenario podría ser hacer de pasarela de peticiones / respuestas FHIR contra un repositorio externo, gestionando el paso de tokens OAuth. image

Y finalmente podríamos pensar quizá en recibir peticiones FHIR para reenviarlas a un servicio FHIR externo, pero pudiendo extraer cierta información o manipulando algunos campos el camino. image

Los detalles de la implementación los encontraréis en la aplicación Open Exchange :)

¡Espero que os sirva!

0
0 260
Artículo Ricardo Paiva · ago 11, 2022 3m read

Gracias a las últimas mejoras al soporte de Python en IRIS y al continuo trabajo en el soporte a la DB-API de Python por parte de InterSystems, he implementado el soporte de IRIS en el proyecto Django, en el que la DB-API de Python se usa para trabajar con otras bases de datos.

Vamos a probar una sencilla aplicación en Django, que almacena sus datos en IRIS.

todo App

0
1 127
InterSystems Official David Reche · ago 8, 2022

Esta es el cuarta de una serie de lanzamientos que forman parte del programa de versiones de prueba 2022.2 para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Se han añadido muchas actualizaciones y mejoras en 2022.2, en la gestión de SQL, integración cloud, adaptadores Kafka y JMS, SQL Loader y otras áreas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor productoEl Programa de Acceso

0
0 106
Artículo Alberto Fuentes · ago 4, 2022 11m read

Al igual que los servidores hardware, los servidores virtuales en nubes públicas y privadas pueden generar cuellos de botella en los recursos, según aumentan las cargas de trabajo. Si utilizas y administras instancias de InterSystems IRIS implementadas en nubes públicas o privadas, es posible que te hayas encontrado la situación en la que para solucionar problemas de rendimiento o de otro tipo se requiere aumentar la capacidad del servidor de una instancia (es decir, escalar verticalmente).

Un motivo frecuente es la memoria insuficiente. Como se describe en la Administración de la memoria y escalamiento de InterSystems IRIS que se encuentra en la Guía de escalabilidad, proporcionar suficiente memoria para todas las estructuras que se ejecutan en el servidor de una instancia de InterSystems IRIS en todas las circunstancias normales de funcionamiento, es un factor crítico tanto para el rendimiento como para la disponibilidad. En un escenario común, conforme aumenta la carga de trabajo en una instancia de InterSystems IRIS, su conjunto de trabajo se vuelve demasiado grande para ser contenido por la memoria caché reservada para las estructuras de la base de datos. Esto lo obliga a que algunas consultas tengan que ir a disco, lo que aumenta significativamente el número de lecturas requeridas del disco y crea un problema importante de rendimiento. Aumentar el tamaño de esta memoria caché resuelve ese problema, pero si al hacerlo no queda suficiente memoria para otros propósitos, también habrá que aumentar la memoria física total del servidor para evitar que el cuello de botella se desplace hacia otra parte del sistema.

Afortunadamente, escalar un servidor virtual generalmente es mucho más sencillo que escalar uno hardware. En esta publicación se analizan las dos etapas del proceso:

  • Cómo escalar los recursos del servidor virtual 

Se puede cambiar la especificación de recursos de un servidor virtual en AWS, GCP y Azure, utilizando la línea de comandos, la API o el portal de la plataforma. VMWare vSphere permite modificar fácilmente varios parámetros de los recursos para una máquina virtual mediante su interfaz de cliente vSphere.

  • Cómo reconfigurar InterSystems IRIS para aprovechar los recursos escalados

Hay varias maneras de reconfigurar InterSystems IRIS para aprovechar los recursos del servidor escalado. Este documento describe el uso de la función Combinar la configuración, que combina nuevos valores de los parámetros, especificados en un archivo combinado, en el CPF de una instancia. Combinar la configuración es un método sencillo y eficaz porque permite ocuparse únicamente de la configuración que se quiere modificar, hacer varios cambios en la configuración de una instancia con una sola operación y realizar fácilmente el mismo conjunto de cambios en varias instancias.

Los procedimientos descritos aquí son manuales, pero en producción muy probablemente serían automatizados, por ejemplo usando un script que aplicaría un archivo combinado específico en una ubicación accesible para una lista de instancias.

Cómo escalar los recursos del host virtual

Las plataformas publicas en la nube ofrecen una variedad de plantillas de recursos para elegir, que especifican el CPU, la memoria, las interfaces de red y otros recursos para hosts virtuales (el almacenamiento se suministra y se dimensiona por separado). Para cambiar el tamaño de un servidor, hay que cambiar la plantilla seleccionada cuando se creó el host a una permita especificar los recursos que necesitas aumentar. En Amazon Web Services, la plantilla de recursos se denomina un tipo de instancia, por ejemplo, el tipo de instancia t3.large especifica 2 CPUs y 8 GB de memoria. En la plataforma Google Cloud es un tipo de máquina, como la e2-standard-2 (que también incluye 2 CPUs y 8 GB), y en Microsoft Azure es un tamaño (el Standard_B2ms requiere igualmente 2 CPUs y 8 GB). Al redefinir el tipo de instancia, tipo de máquina o tamaño del servidor de una nube pública existente, se pueden escalar las especificaciones de sus recursos. En una nube privada de VMware vSphere, se puede utilizar la interfaz de cliente vSphere en la consola de administración vCenter Server para modificar directamente una o más configuraciones de los recursos individuales de una máquina virtual existente. (También se pueden escalar simultáneamente grupos de servidores en cada plataforma).

En las siguientes secciones se ofrecen breves ejemplos sobre cómo redimensionar servidores virtuales individuales en distintas plataformas, con enlaces a la documentación para todos los métodos disponibles. Ten en cuenta que estos métodos (API, interfaces de línea de comandos e interfaces del portal) se proporcionan y mantienen gracias a los proveedores en la nube, y los ejemplos que aquí se incluyen son con propósitos informativos, para ilustrar con qué facilidad se puede adaptar InterSystems IRIS para aprovechar el aumento en los recursos. 

AWS

Para modificar el tipo de instancia de un servidor AWS (denominada instance, no debe confundirse con una instancia de InterSystems IRIS) se puede utilizar el comando CLI modify-instance-attribute, como se muestra en el siguiente ejemplo:

$ aws ec2 describe-instances --instance-ids i-01519f663af48a55e
{
   "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-0abcdef1234567890,
            "InstanceId": "i-1234567890abcdef0,
            "InstanceType": "m5n.large",
            ...
$ aws ec2 stop-instances --instance-ids i-01519f663af48a55e
{
    "StoppingInstances": [
        {
            "InstanceId": "i-1234567890abcdef0",
            ...
$ aws ec2 describe-instances --instance-ids i-01519f663af48a55e
{
   "Instances": [
        {
            ...
            "State": {
            "Code": 80, 
            "Name": "stopped"
            }
            ...
$ aws ec2 modify-instance-attribute --instance-ids i-01519f663af48a55e \
      --instance-type "{\"Value\": \"m5n.xlarge\"}"
$ aws ec2 start-instances --instance-ids i-01519f663af48a55e
{
    "StartingInstances": [
        {
            "InstanceId": "i-1234567890abcdef0",
            "CurrentState": {
                "Code": 0,
                "Name": "pending"
            },
            "PreviousState": {
                "Code": 80,
                "Name": "stopped"
            ...
$ aws ec2 describe-instances --instance-ids i-01519f663af48a55e
{
   "Instances": [
        {
            "AmiLaunchIndex": 0,
            "ImageId": "ami-0abcdef1234567890,
            "InstanceId": "i-1234567890abcdef0,
            "InstanceType": "m5n.xlarge",
            ...

También se puede hacer este cambio mediante la llamada a la API de AWS ModifyInstanceAttribute o con la consola AWS EC2

GCP

Para modificar el tipo de máquina de un servidor GCP (también conocida como una instance), se puede usar el comando gcloud CLI para detener, modificar y reiniciar la instancia. Por ejemplo, se podrían usar los siguientes comandos para modificar el tipo de máquina de una instancia llamada scalingTest por n1-highmem-96:

$ gcloud compute instances stop scalingTest
$ gcloud compute instances set-machine-type scalingTest --machine-type n1-highmem-32
$ gcloud compute instances start scalingTest

También se puede hacer este cambio usando la Google Cloud Console o la API de la GCP.

Azure

Cuando se utiliza Azure CLI para modificar el tamaño de una máquina virtual con Linux, se puede ver una lista de los tamaños disponibles en el clúster de hardware donde se aloja la máquina virtual usando el comando list-vm-resize-options, por ejemplo:

az vm list-vm-resize-options --resource-group testingGroup --name scalingTest --output table

Se puede utilizar el comando resize para cambiar el tamaño de la máquina virtual a una de las opciones en la lista, como se muestra en el ejemplo. Este comando reinicia la máquina virtual automáticamente.

az vm resize --resource-group testingGroup --name scalingTest --size Standard_E32d_v4

Si el tamaño al que quieres cambiar la máquina virtual no está disponible, puede anular la asignación de la máquina virtual, que puede ser redimensionada a cualquier tamaño que esté soportado por la región y reiniciarse. Los comandos relacionados se muestran a continuación:

az vm deallocate --resource-group testingGroup --name scalingTest
az vm resize --resource-group testingGroup --name scalingTest --size Standard_M128s
az vm start --resource-group testingGroup --name scalingTest

Se puede cambiar el tamaño de una máquina virtual de Windows en Azure utilizando el portal de Azure o los comandos de Powershell.

vSphere

Para cambiar el tamaño de una máquina virtual de VMware vSphere, hay que hacer lo siguiente:

  1. Abrir el cliente vSphere o el cliente web y mostrar el inventario de la máquina virtual.
  2. Haga clic con el botón derecho en la máquina virtual que quieres modificar y seleccionar Edit Settings.
  3. En la etiqueta Virtual Hardware
    • Expande Memory y cambia la cantidad de RAM configurada para la máquina virtual.
    • Expande CPU y cambia el número de núcleos y, de manera opcional, el número de núcleos por socket.
    • Realiza cualquier otro cambio que quieras en los recursos de hardware asignados a la máquina virtual.

Cómo reconfigurar InterSystems IRIS para aprovechar los recursos escalados

Cuando hayas escalado el servidor, el siguiente paso es reconfigurar InterSystems IRIS para aprovechar el aumento de recursos cambiando uno o más parámetros en el archivo de parámetros de configuración de la instancia (CPF). Por ejemplo, para continuar con el escenario mencionado al principio de esta publicación, ahora que has aumentado los recursos de memoria del servidor, querrás aprovecharte de esto aumentando el tamaño de la caché de la base de datos de la instancia de InterSystems IRIS (que se realiza cambiando el valor del parámetro globals) para que pueda mantener más datos en la memoria.

Una manera sencilla de realizar este tipo de cambios, y con mucho la forma más fácil y repetible para realizar varios cambios en la configuración de una instancia en una sola operación o de realizar los mismos cambios en varias instancias, es utilizar la función Combinar la configuración, que está disponible en los sistemas UNIX® y Linux. Como se describe en Cómo usar la función Combinar la configuración para implementar instancias personalizadas de InterSystems IRIS en Cómo ejecutar productos de InterSystems en contenedores y en Cómo usar la función Combinar la configuración en la Referencia del Archivo de Configuración de Parámetros, la función Combinar la configuración permite especificar un archivo de combinación que contenga la configuración que quieres combinar en el CPF de una instancia, inmediatamente antes de un reinicio.  (En la versión 2021.1 podrás hacer esto en una instancia que está en ejecución sin reiniciarla). Esto no solo es más conveniente que editar directamente el CPF de una instancia, sino que es altamente repetible en varias instancias, y es compatible con una gestión de cambios confiables, ya que permite mantener un historial preciso de los cambios simplemente adaptando la configuración de los archivos combinados a los que los aplique.

Para realizar la función Combinar la configuración, hay que hacer lo siguiente:

  1. Crear el archivo combinado con los parámetros que quieres modificar.
  2. Colocar el archivo combinado en una ubicación accesible a la instancia. Si la instancia que estás modificando se encuentra en un contenedor (el cual es probable que esté en un host de la nube), puedes preparar el archivo en el directorio %SYS duradero de la instancia (consulta %SYS duradero para datos persistentes de la instancia en Cómo ejecutar productos de InterSystems en contenedores).
  3. Especifique la ubicación del archivo combinado utilizando la variable de entorno ISC_CPF_MERGE_FILE antes de reiniciar la instancia.

Por ejemplo, siguiendo con el caso de la caché de la base de datos que necesita una actualización, supongamos que queremos aumentar a 100 GB el tamaño de la caché de la base de datos de una instancia en un contenedor. La configuración, en la sección [config] del CPF, sería globals=102400, que establece la caché de la base de datos para bloques de 8 kilobytes en 102,400 MB, o 100 GB. (Como se explica en la descripción de los globals en la Referencia del Archivo de Configuración de Parámetros, el parámetro establece el tamaño de la caché para varios tamaños de bloque; sin embargo, si solo se proporciona un valor, se aplica al tamaño de bloque de 8 kilobytes, y se asume **** [zero] para los otros tamaños; globals=102400 es, por lo tanto, el equivalente a globals=0,0,102400,0,0,0).

Para realizar este cambio, se puede realizar lo siguiente en el host de la nube:

1. Crear una configuración en el archivo combinado, denominado por ejemplo mergefile2021.06.30.cpf, que contenga estas líneas:

[config]
globals=102400

2. Colocar el archivo combinado en el directorio %SYS duradero que se encuentra en el sistema de archivos del host, el cual si se instaló el volumen externo /data como /external en el contenedor y se usó la variable ISC_DATA_DIRECTORY para especificar /external/iris_durable como el directorio %SYS duradero para la instancia, sería /data/iris_durable.

3. Utilizar el comando docker exec en la línea de comandos del host para especificar la variable y reiniciar la instancia con el comando iris si el contenedor de la instancia se llama iris y la instancia se llama IRIS, por ejemplo, el comando tendrá el siguiente aspecto:

docker exec iris ISC_CPF_MERGE_FILE=/data/iris_durable/mergefile2021.06.30.cpf 
iris stop IRIS restart
  1. Cuando la instancia se reinicie, se podrá confirmar la nueva configuración de globals con este comando:
docker exec iris grep globals /data/iris_durable/iris.cpf
1
0 130
Artículo Alberto Fuentes · abr 22, 2022 4m read

Durante una actualización a una versión principal (major) es aconsejable recompilar las clases y rutinas de todos tus namespaces (ver Tareas tras la instalación de una versión major).

do $system.OBJ.CompileAllNamespaces("u")
do ##Class(%Routine).CompileAllNamespaces()

Para automatizar esta tarea de administración y mantener un registro de cualquier error, os muestro un ejemplo de una clase para importar y compilar en el namespace USER, que puedes usar después de cada actualización: admin.utils.cls

1
0 183
Anuncio Mario Sanchez Macias · jul 28, 2022

Docker 20.10.14 (lanzado el 23 de marzo de 2022) cambia las funcionalidades que Linux da a los contenedores de una manera que es incompatible con el Linux capability checkeren los contenedores de InterSystems IRIS 2021.1 (y posteriores). 

Los usuarios ejecutando Docker 20.10.14 en Linux encontrarán que los contenedores de IRIS 2021.1+ fallarán al iniciarse y los logs reportarán de forma incorrecta que las funcionalidades requeridas de Linux no se encuentran. Por ejemplo:

0
0 105
InterSystems Official David Reche · jul 26, 2022

Esta es el tercera de una serie de lanzamientos que forman parte del programa de versiones de prueba para desarrolladores. Las próximas versiones de prueba se espera que sean actualizadas cada dos semanas, aproximadamente, y añadiremos funcionalidades según estén listas. Se han añadido muchas actualizaciones y mejoras en 2022.2, en la gestión de SQL, integración cloud, adaptadores Kafka y JMS, SQL Loader y otras áreas. Compartid, por favor, vuestro feedback a través de la Comunidad de Desarrolladores, para que entre todos podamos desarrollar un mejor producto

0
0 177
Artículo Muhammad Waseem · jul 26, 2022 10m read

La fecha y la hora son factores importantes en nuestra vida. Porque todas las aplicaciones son interesantes según la fecha y la hora. Pero el mundo está dividido en múltiples zonas horarias. Si nuestro producto se lanza al mundo, para mantener el historial de eventos, debemos convertir todas las horas a nuestra hora local o UTC (Tiempo Universal Coordinado). Por lo que sé, muchos lenguajes de programación conocidos de C#, JavaScript, Java, etc., ofrecían la librería para convertir la fecha y la hora, es decir, con un nombre de zona horaria podemos convertir sin conocer la diferencia horaria.

La base de datos TZ no existe en los productos de InterSystems. En el pasado, escribí la función en C# (C# tiene una librería para esto) y la usé dentro de InterSystems como una clase contenedora.

Pero ahora, IRIS comenzó a ser compatible con Python Embebido. Por eso, podemos usar la conversión de zona horaria de Python en InterSystems fácilmente.

0
0 999
Artículo Ricardo Paiva · jul 25, 2022 2m read

Google tiene una interesante herramienta llamada Google Data Studio. Esta aplicación permite crear cuadros de mando (dashboards) interactivos, con tus datos, disponibles en internet. Además, ofrece cientos de conectores con cualquier fuente de datos, desarrollados por la comunidad. Y también visualizadores desarrollados por la comunidad. Lo más importante es que Google ofrece una forma de desarrollar tu propio conector con tus datos. 

FHIRaaS ofrece una REST API, y está disponible desde internet. Así que he decidido probar a crear un informe básico con los datos almacenados allí. Y al final, conseguí esto.

0
0 176
Artículo Alberto Fuentes · abr 28, 2021 8m read

Introducción

Si resuelves problemas complejos en ObjectScript, probablemente tienes mucho código que funciona con los valores de %Status. Si has interactuado con clases persistentes desde una perspectiva de objetos (%Save, %OpenId, etc.), casi seguro que las ha visto. 

Un %Status proporciona una envoltura alrededor de un mensaje de error localizable en las plataformas de InterSystems. Un estado OK ($$$OK) simplemente es igual a 1, mientras que un mal estado ($$$ERROR(errorcode,arguments...)) se representa como un 0 seguido de un espacio seguido de una lista $ListBuild con información estructurada sobre el error.

$System.Status (mira la referencia de clase) proporciona varias APIs útiles para trabajar con los valores de %Status; la referencia de clase es útil y no os molestaré duplicándola aquí. También ha habido algunos otros artículos/preguntas útiles sobre el tema (consulta los enlaces al final de esta publicación). En este artículo me centraré en algunas técnicas de depuración en vez de escribir las prácticas recomendadas (de nuevo, si las estás buscando, consulta los enlaces al final).

Ejemplo de código motivador

Nota: ¡nunca escribas un código como este! :) Revisa siempre tus estados y devuélvelos/lánzalos como excepciones (por ejemplo, $$$ThrowStatus(someErrorStatus)) y hará que la depuración sea MUY sencilla.

Class DC.Demo.MaskedErrorStatus Extends %Persistent
{

Property Answer As %TinyInt;

ClassMethod Run() As %Status
{
    Set instance = ..%New()
    Set instance.Answer = 9000
    Do instance.%Save()
    
    Set instance = ..%OpenId(1,,.sc)
    Set instance.Answer = 42
    Do instance.%Save()
    
    Quit $$$OK
}

}

Cuando se ejecuta desde el terminal, se lanza una excepción; es evidente que algo salió mal.

USER>d ##class(DC.Demo.MaskedErrorStatus).Run()
 
 Set instance.Answer = 42
 ^
&lt;INVALID OREF>zRun+5^DC.Demo.MaskedErrorStatus.1

Truco #1 de depuración con %Status: $System.OBJ.DisplayError()

Siempre puedes ejecutar $System.OBJ.DisplayError() para imprimir el último estado de error que se creó. Esto funciona porque cada vez que se crea un estado de error (por ejemplo, por medio de $System.Status.Error), la variable %objlasterror se establece en ese estado. También puedes utilizar zwrite %objlasterror (de forma equivalente). En el caso anterior:

USER 2d1>d $system.OBJ.DisplayError()
ERROR #5809: Object to Load not found, class 'DC.Demo.MaskedErrorStatus', ID '1'

Truco #2 de depuración con %Status: seguimiento de stacks

Dentro de cada %Status hay un seguimiento del stack (pila de llamadas) en el que se creó el error. Se puede ver esto al utilizar el estado zwrite:

USER 2d1>zw %objlasterror %objlasterror="0 "_$lb($lb(5809,"DC.Demo.MaskedErrorStatus","1",,,,,,,$lb(,"USER",$lb("e^%LoadData+18^DC.Demo.MaskedErrorStatus.1^1","e^%Open+16^%Library.Persistent.1^1","e^%OpenId+1^%Library.Persistent.1^1","e^zRun+4^DC.Demo.MaskedErrorStatus.1^1","d^^^0"))))/* ERROR #5809: Object to Load not found, class 'DC.Demo.MaskedErrorStatus', ID '1' */

¿Quieres ver el seguimiento de stacks en el texto de error (que es más sencillo de utilizar) para cada estado (por ejemplo, utilizando $System.OBJ.DisplayError() o $System.Status.GetErrorText(someStatus))? Puedes hacerlo al establecer `%oddENV("callererrorinfo",$namespace)' a valores 1 o 2. Puedes ver el efecto aquí:

USER>set ^%oddENV("callererrorinfo",$namespace)=1
USER>d $system.OBJ.DisplayError()
ERROR #5809: Object to Load not found, class 'DC.Demo.MaskedErrorStatus', ID '1' [%LoadData+18^DC.Demo.MaskedErrorStatus.1:USER]
USER>set ^%oddENV("callererrorinfo",$namespace)=2
USER>d $system.OBJ.DisplayError()
ERROR #5809: Object to Load not found, class 'DC.Demo.MaskedErrorStatus', ID '1' [e^%LoadData+18^DC.Demo.MaskedErrorStatus.1^1 e^%Open+16^%Library.Persistent.1^1 e^%OpenId+1^%Library.Persistent.1^1 e^zRun+4^DC.Demo.MaskedErrorStatus.1^1 d^^^0:USER]
USER>k ^%oddENV("callererrorinfo",$namespace)
USER>d $system.OBJ.DisplayError()
ERROR #5809: Object to Load not found, class 'DC.Demo.MaskedErrorStatus', ID '1'

Ten en cuenta que esto sólo es apropiado en un entorno de desarrollo - no querrás que tus usuarios vean el interior de tu código -. En realidad, es mejor evitar mostrar los valores de %Status directamente a los usuarios. Son preferibles los mensajes de error específicos de la aplicación, más fáciles de utilizar. Pero ese es un tema para otro día.

Truco #3 de depuración con %Status: el elegante zbreak

Aquí es donde se pone difícil - en el caso de este fragmento de código, la causa raíz es un %Status no verificado de %Save() que antes estaba en el fragmento de código. Es fácil imaginar un ejemplo mucho más complicado en el que encontrar lo que ha fallado es realmente difícil, especialmente si se trata de un error que se produce en algún punto del código de la plataforma. Mi método preferido para gestionar esto, sin saltar a un depurador interactivo, es utilizar un comando zbreak en el terminal:

USER>zbreak *%objlasterror:"N":"$d(%objlasterror)#2":"set ^mtemptl($i(^mtemptl))=%objlasterror"

...¿qué quiere decir eso?

zbreak <cada vez que %objlasterror cambie>:<no haga nada en el depurador mismo>:<mientras %objlasterror esté definido y tenga un valor (por ejemplo, no ha pasado de estar definido a estar indefinido)>:<ejecuta el código para establecer el siguiente subíndice de un global con un subíndice entero que no está en journal (porque comienza con mtemp, en caso de que estemos en una transacción cuando se crea %Status y se haya revertido para cuando observemos el registro; también, con mis iniciales como parte del global para que si alguien lo encuentra en el código comprometido o en una base de datos inflada sepa que debe llamarme) al estado de error>

Nota adicional sobre zbreak: puedes ver los breakpoints/watchpoints definidos actualmente si ejecutas "zbreak" sin argumentos, y puedes/debes desactivar estos breakpoints cuando hayas terminado con ellos ejecutando break "off", por ejemplo:

USER>zbreak
BREAK:
 No breakpoints
%objlasterror F:E S:0 C:"$d(%objlasterror)#2" E:"set ^mtemptl($i(^mtemptl))=%objlasterror"
USER>break "off"
USER>zbreak
BREAK:
 No breakpoints
 No watchpoints

Entonces, ¿qué sucede cuando el método problemático se ejecuta con el watchpoint establecido?

USER>zbreak *%objlasterror:"N":"$d(%objlasterror)#2":"set ^mtemptl($i(^mtemptl))=%objlasterror"
 
USER>d ##class(DC.Demo.MaskedErrorStatus).Run()
 
 Set instance.Answer = 42
 ^
&lt;INVALID OREF>zRun+5^DC.Demo.MaskedErrorStatus.1
 
USER 2d1>zw ^mtemptl
^mtemptl=6
^mtemptl(1)="0 "_$lb($lb(7203,9000,127,,,,,,,$lb(,"USER",$lb("e^zAnswerIsValid+1^DC.Demo.MaskedErrorStatus.1^1","e^%ValidateObject+3^DC.Demo.MaskedErrorStatus.1^4","e^%SerializeObject+3^%Library.Persistent.1^1","e^%Save+4^%Library.Persistent.1^2","d^zRun+3^DC.Demo.MaskedErrorStatus.1^1","d^^^0"))))/* ERROR #7203: Datatype value '9000' greater than MAXVAL allowed of 127 */
^mtemptl(2)="0 "_$lb($lb(7203,9000,127,,,,,,,$lb(,"USER",$lb("e^zAnswerIsValid+1^DC.Demo.MaskedErrorStatus.1^1","e^%ValidateObject+3^DC.Demo.MaskedErrorStatus.1^4","e^%SerializeObject+3^%Library.Persistent.1^1","e^%Save+4^%Library.Persistent.1^2","d^zRun+3^DC.Demo.MaskedErrorStatus.1^1","d^^^0")),"0 "_$lb($lb(5802,"DC.Demo.MaskedErrorStatus:Answer",9000,,,,,,,$lb(,"USER",$lb("e^EmbedErr+1^%occSystem^1"))))))/* ERROR #7203: Datatype value '9000' greater than MAXVAL allowed of 127-   > ERROR #5802: Datatype validation failed on property 'DC.Demo.MaskedErrorStatus:Answer', with value equal to "9000" */
^mtemptl(3)="0 "_$lb($lb(7203,9000,127,,,,,,,$lb("zAnswerIsValid+1^DC.Demo.MaskedErrorStatus.1","USER",$lb("e^zAnswerIsValid+1^DC.Demo.MaskedErrorStatus.1^1","e^%ValidateObject+3^DC.Demo.MaskedErrorStatus.1^4","e^%SerializeObject+3^%Library.Persistent.1^1","e^%Save+4^%Library.Persistent.1^2","d^zRun+3^DC.Demo.MaskedErrorStatus.1^1","d^^^0"))))/* ERROR #7203: Datatype value '9000' greater than MAXVAL allowed of 127 */
^mtemptl(4)="0 "_$lb($lb(5802,"DC.Demo.MaskedErrorStatus:Answer",9000,,,,,,,$lb("EmbedErr+1^%occSystem","USER",$lb("e^EmbedErr+1^%occSystem^1"))))/* ERROR #5802: Datatype validation failed on property 'DC.Demo.MaskedErrorStatus:Answer', with value equal to "9000" */
^mtemptl(5)="0 "_$lb($lb(7203,9000,127,,,,,,,$lb("zAnswerIsValid+1^DC.Demo.MaskedErrorStatus.1","USER",$lb("e^zAnswerIsValid+1^DC.Demo.MaskedErrorStatus.1^1","e^%ValidateObject+3^DC.Demo.MaskedErrorStatus.1^4","e^%SerializeObject+3^%Library.Persistent.1^1","e^%Save+4^%Library.Persistent.1^2","d^zRun+3^DC.Demo.MaskedErrorStatus.1^1","d^^^0")),"0 "_$lb($lb(5802,"DC.Demo.MaskedErrorStatus:Answer",9000,,,,,,,$lb("EmbedErr+1^%occSystem","USER",$lb("e^EmbedErr+1^%occSystem^1"))))))/* ERROR #7203: Datatype value '9000' greater than MAXVAL allowed of 127-   > ERROR #5802: Datatype validation failed on property 'DC.Demo.MaskedErrorStatus:Answer', with value equal to "9000" */
^mtemptl(6)="0 "_$lb($lb(5809,"DC.Demo.MaskedErrorStatus","1",,,,,,,$lb(,"USER",$lb("e^%LoadData+18^DC.Demo.MaskedErrorStatus.1^1","e^%Open+16^%Library.Persistent.1^1","e^%OpenId+1^%Library.Persistent.1^1","e^zRun+4^DC.Demo.MaskedErrorStatus.1^1","d^^^0"))))/* ERROR #5809: Object to Load not found, class 'DC.Demo.MaskedErrorStatus', ID '1' */

Hay un poco de ruido ahí, pero el problema clave salta a la vista:

/* ERROR #7203: Datatype value '9000' greater than MAXVAL allowed of 127 */

¡Debería haber sabido que no debería utilizar %TinyInt! (Y, lo que es más importante, siempre debes verificar los valores de %Status devueltos por los métodos que llamas).

Lecturas relacionadas

Mis patrones de codificación preferidos para la gestión y reporte de errores
%Status frente a otros valores de retorno en los métodos ObjectScript de Caché
Sobre %objlasterror
Cómo configurar $$$envCallerErrorInfoGet
Fragmentos de código para gestión de errores de ObjectScript
Comando ZBREAK

1
1 220
Artículo Kurro Lopez · jul 10, 2022 1m read

Durante mucho tiempo hemos estado usando una utilidad en producción para exportar el resultado de una consulta a una hoja de cálculo Excel. Además, hemos hecho una modificación en ella, en la que la configuración explícita de los formatos de las columnas es una prioridad.

Esta utilidad usaba el módulo %SYS.ZENReportExcelExporter y se basa en un programa java. Todos los años el informe crecía y no había suficiente memoria RAM en java, por lo que teníamos que aumentar el valor de la variable entorno. El valor ha alcanzado los 7gb y se ha convertido en un problema.

Así que decidimos buscar y crear un sustituto de la utilidad. Obviamente, busqué en python y la librería openxl.

Formando parte del Programa de Acceso Preferente a Python Embebido, implementé un pequeño ejemplo y lo publiqué en OpenExchange. Os invito a todos los que queráis participar en el desarrollo de la funcionalidad.

Estad atentos a la versión final y puesta en producción.

0
0 199