Limpiar filtro
Pregunta
Laura Blázquez García · 24 abr, 2025
Hola!
Recientemente he estado probando a crear nuestro propio repositorio de paquetes con IPM. He podido crearlo sin problemas, y he visto que, al final, nuestro repositorio IPM no deja de ser una instancia de IRIS. En el ejemplo del que he partido, utiliza la versión community. Y mi pregunta es, para tener nuestro repositorio disponible para toda la compañía, ¿podemos seguir con la versión community, o debe ser una versión enterprise con licencia?
Y ya que estoy, ¿hay alguna forma de saber qué paquetes se han descargado, y por quién?
Muchas gracias! ¡Buenas @Laura.BlázquezGarcía !
Por aquí tienes un artíc@Evgeny.Shvarov al respecto de la creación y publicación de proyectos en el IPM, básicamente es añadir el archivo module.xml con determinados parámetros para que capture el código que quieras publicar. Posteriormente le mandas un mensaje y el incluye vuestro proyecto al repositorio del IPM. Hola @LuisAngel.PérezRamos!
No veo el link al artículo, quizá te refieras a alguno de estos?
https://community.intersystems.com/post/why-docker-ipm-and-objectscript-quality-are-important
https://community.intersystems.com/post/installing-objectscript-solutions-without-source-code-or-deploy-mode-using-ipm-package-manager
De todas formas, mi pregunta va sobre tener nuestro propio repositorio IPM, privado. Es decir, crear nuestro propio registro. Lo he conseguido hacer en local, la verdad es que con la template que hay en el github de la comunidad ha sido muy fácil. Pero a la hora de tenerlo disponible para toda la compañía y empezar a subir nuestras propias librerías, antes de arrancarlo con la versión que hay ahora, etc, quería saber si es conveniente crearlo en una versión IRIS enterprise, o vale con que sea una IRIS Community.
Gracias! Perdona, que te contesté desde el móvil y me comí la URL:
https://community.intersystems.com/post/setting-your-own-intersystems-objectscript-package-manager-registry No había visto ese artículo, pero más o menos es lo que he seguido. No he instalado zpm-registry en una instancia de IRIS que ya teníamos, sino que he levantado un contenedor nuevo, con la versión community.
Nuestro caso es que trabajamos para clientes que tienen IRIS, cada uno el suyo, pero tenemos librerías comunes que utilizamos en estos clientes. Mi idea era levantar un registry propio para nuestra compañía, en la que tener estas librerías disponibles para cualquier cliente, y en caso de que cada cliente lo necesite, levantar en sus instancias su registry privado.
Entiendo, entonces, que lo ideal es tener el registry levantado en la instancia de IRIS que ya tengamos, y no utilizar un contenedor aparte con una versión Community. Es así? A priori debería dar igual la versión de IRIS porque la Community me parece que no está limitada, pero si lo que vais a hacer es algo más corporativo deberíais usar vuestra licencia de IRIS licenciada.
Artículo
Ricardo Paiva · 10 nov, 2022
Hace tiempo presenté un nuevo driver para Django for IRIS. Ahora voy a mostrar cómo utilizar Django con IRIS en la práctica.
Nota importante: Django no funciona bien con la Community Edition de IRIS. La Community Edition solo tiene disponibles 5 conexiones, y Django las usará muy rápido. Así que, desafortunadamente por esta razón no puedo recomendar este método para desarrollar nuevas aplicaciones, debido a la dificultad de predecir el uso de la licencia.
Inicio del proyecto Django
Para empezar, tenemos que instalar Django
pip install django
Después, creamos un proyecto llamado demo. Creará una carpeta de proyectos con el mismo nombre
django-admin startproject demo
cd demo
o se puede hacer en una carpeta existente
django-admin startproject main .
Este comando genera unos pocos archivos python para nosotros.
Donde:
manage.py: utilidad de línea de comando que permite interactuar con este proyecto Django de varias maneras
directorio main: es el paquete Python actual para vuestro proyecto
main/__init__.py: un archivo vacío que dice a Python que este directorio debería ser consideredo un paquete Python
main/settings.py: settings/configuración para este proyecto Django
main/urls.py: Las declaraciones URL para este proyecto Django; un “índice” de vuestro sitio con la funcioanlidad de Django
main/asci.py: Un punto de entrada para servidores web compatibles con ASGI para atender vuestro proyecto
main/wsci.py: Un punto de entrada para servidores web compatibles con WSGI para atender vuestro proyecto
Incluso desde este punto podemos empezar nuestro proyecto y, de alguna manera, funcionará
$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced). You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
July 22, 2022 - 15:24:12
Django version 4.0.6, using settings 'main.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Ahora, se puede ir al navegador y abrir la URL http://127.0.0.1:8000 allí
Añadir IRIS
Vamos a añadir acceso a IRIS, y para hacerlo necesitamos instalar unas cuantas dependencias de nuestro proyecto, y la forma correcta de hacerlo es definirlo en el archivo llamado requirements.txt con este contenido, donde deberíamos añadir django como una dependencia
# Django itself
django>=4.0.0
Y después, el driver de IRIS for Django, publicado. Desafortunadamente, InterSystems no quiere publicar drivers propios en PyPI, así que tenemos que definirlo de esta manera más "fea". Estad atentos, pueden eliminarlo en cualquier momento, por lo que puede dejar de funcionar en el futuro. (Si estuviera en pypi, se instalaría como una dependencia de django-iris, no siendo necesaria su definición.)
# InterSystems IRIS driver for Django, and DB-API driver from InterSystems
django-iris==0.1.13
https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/DB-API/intersystems_irispython-3.2.0-py3-none-any.whl
Instalar dependencias definidas en este archivo con comando
pip install -r requirements.txt
Ahora, podemos configurar nuestro proyecto para usar IRIS. Para hacerlo, tenemos que actualizar el parámetro DATABASES en el archivo settings.py, con líneas como esta, en la que NAME apunta al Namespace en IRIS, y la puerta al SuperPort donde tenemos IRIS.
DATABASES = {
'default': {
'ENGINE': 'django_iris',
'NAME': 'USER',
'USER': '_SYSTEM',
'PASSWORD': 'SYS',
'HOST': 'localhost',
'PORT': 1982,
}
}
Django tiene ORM, y modelos almacenados en el proyecto, y requiere modelos de Django sincronizados con Database como tablas. Por defecto, hay unos pocos modelos, relacionados con auth. Y podemos ejecutar migrate ahora
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
Si vamos a IRIS, encontraremos varias tablas extra allí
Definir más modelos
Es el momento de añadir algunos de nuestros modelos. Para hacerlo, añade un nuevo archivo models.py, con contenido como este
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
dob = models.DateField()
sex = models.BooleanField()
Como puedes ver, tiene diferentes tipos de campos. Entonces este modelo tiene que estar preparado para Database. Antes de hacerlo, añade nuestro proyecto main a INSTALLED_APPS en settings.py
INSTALLED_APPS = [
....
'main',
]
Y podemos makemigrations. Este comando tiene que ser llamado después de cualquier cambio en el modelo, se ocupa de los cambios históricos en el modelo, y no importa qué versión de la aplicación está instalada, la migración sabrá cómo actualizar el esquema en la base de datos
$ python manage.py makemigrations main
Migrations for 'main':
main/migrations/0001_initial.py
- Create model Person
Podemos ejecutar migrate otra vez, ya sabe que las migraciones anteriores ya están hechas, así que solo ejecuta la nueva
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, main, sessions
Running migrations:
Applying main.0001_initial... OK
Y, de hecho, podemos ver cómo se ve la migración desde la vista de SQL.
$ python manage.py sqlmigrate main 0001
--
-- Create model Person
--
CREATE TABLE "main_person" ("id" BIGINT AUTO_INCREMENT NOT NULL PRIMARY KEY, "first_name" VARCHAR(30) NULL, "last_name" VARCHAR(30) NULL, "dob" DATE NOT NULL, "sex" BIT NOT NULL);
Pero es posible acceder a las tablas ya existentes en la base de datos, por ejemplo, si ya tienes una aplicación funcionando. Yo tengo el gestor de paquetes zpm package posts-and-tags instalado, vamos a hacer un modelo para la tabla community.posts
$ python manage.py inspectdb community.post
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
# * Rearrange models' order
# * Make sure each model has one field with primary_key=True
# * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models
class CommunityPost(models.Model):
id = models.AutoField(db_column='ID') # Field name made lowercase.
acceptedanswerts = models.DateTimeField(db_column='AcceptedAnswerTS', blank=True, null=True) # Field name made lowercase.
author = models.CharField(db_column='Author', max_length=50, blank=True, null=True) # Field name made lowercase.
avgvote = models.IntegerField(db_column='AvgVote', blank=True, null=True) # Field name made lowercase.
commentsamount = models.IntegerField(db_column='CommentsAmount', blank=True, null=True) # Field name made lowercase.
created = models.DateTimeField(db_column='Created', blank=True, null=True) # Field name made lowercase.
deleted = models.BooleanField(db_column='Deleted', blank=True, null=True) # Field name made lowercase.
favscount = models.IntegerField(db_column='FavsCount', blank=True, null=True) # Field name made lowercase.
hascorrectanswer = models.BooleanField(db_column='HasCorrectAnswer', blank=True, null=True) # Field name made lowercase.
hash = models.CharField(db_column='Hash', max_length=50, blank=True, null=True) # Field name made lowercase.
lang = models.CharField(db_column='Lang', max_length=50, blank=True, null=True) # Field name made lowercase.
name = models.CharField(db_column='Name', max_length=250, blank=True, null=True) # Field name made lowercase.
nid = models.IntegerField(db_column='Nid', primary_key=True) # Field name made lowercase.
posttype = models.CharField(db_column='PostType', max_length=50, blank=True, null=True) # Field name made lowercase.
published = models.BooleanField(db_column='Published', blank=True, null=True) # Field name made lowercase.
publisheddate = models.DateTimeField(db_column='PublishedDate', blank=True, null=True) # Field name made lowercase.
subscount = models.IntegerField(db_column='SubsCount', blank=True, null=True) # Field name made lowercase.
tags = models.CharField(db_column='Tags', max_length=350, blank=True, null=True) # Field name made lowercase.
text = models.CharField(db_column='Text', max_length=-1, blank=True, null=True) # Field name made lowercase.
translated = models.BooleanField(db_column='Translated', blank=True, null=True) # Field name made lowercase.
type = models.CharField(db_column='Type', max_length=50, blank=True, null=True) # Field name made lowercase.
views = models.IntegerField(db_column='Views', blank=True, null=True) # Field name made lowercase.
votesamount = models.IntegerField(db_column='VotesAmount', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'community.post'
Está marcado como managed = False, lo que significa que makemigrations y migrate no funcionarán para esta tabla. Omitiendo el nombre de la tabla, producirá una lista larga de módulos, incluyendo las tablas ya creadas con Django previamente.
Artículo
Nancy Martínez · 7 ago, 2019
¡Hola a tod@s!Este artículo es una pequeña descripción general de una herramienta que permitirá entender las clases y su estructura, dentro de los productos de InterSystems: desde IRIS hasta Caché, Ensemble y HealthShare.En resumen, con esta herramienta se visualiza una clase o un paquete completo, se muestran las relaciones que existen entre las clases y proporciona toda la información que se encuentra disponible para los desarrolladores y líderes de equipos sin necesidad examinar el código, utilizando el Studio.Si estás aprendiendo a utilizar los productos de InterSystems, o simplemente estás interesado en aprender algo nuevo sobre las soluciones que ofrece la tecnología de InterSystems, ¡eres más que bienvenido a leer la descripción general de ObjectScript Class Explorer! Introducción a los productos de InterSystemsIRIS (anteriormente conocido como Caché) es una DBMS Base de Datos Multi Modelo. Es posible acceder a los datos mediante consultas SQL o al interactuar con los objetos y procedimientos almacenados por las interfaces que están disponibles para varios lenguajes de programación. Pero la primera opción siempre es desarrollar aplicaciones en el lenguaje nativo e integrado de la DBMS— ObjectScript (COS).Caché es compatible con las clases que se encuentran en el nivel de la DBMS. Existen dos principales tipos de clases: Persistentes (pueden almacenarse en la base de datos) y registradas (no se almacenan en la base de datos y desempeñan el papel de programas y controladores). Además, existen varios tipos de clases especiales: Serial (son clases que pueden integrarse en clases persistentes para crear tipos de datos complejos, como por ejemplo direcciones), DataType (se utiliza para crear tipos de datos definidos por el usuario), Index, View y Stream.Class ExplorerCaché Class Explorer es una herramienta que visualiza la estructura de las clases de Caché como un diagrama, muestra las dependencias que existen entre las clases y toda la información importante, incluido el código de los métodos, consultas, bloques xData, comentarios, documentos de apoyo y palabras clave de varios elementos de las clases.FuncionalidadClass Explorer utiliza una versión extendida del estándar UML para la visualización, debido a que Caché cuenta con un conjunto adicional de entidades que no son compatibles con el estándar UML , pero que son importantes para Caché: consultas, bloques xData, muchas de las palabras clave para los métodos y propiedades (como por ejemplo: System, ZenMethod, Hidden, ProcedureBlock), relaciones padre/ hijo, de uno a muchos, tipos de clase, entre otras.Caché Class Explorer (version 1.14.3) te permitirá hacer lo siguiente:Visualizar la jerarquía de los paquetes, un diagrama de clases o el paquete completo,Editar la apariencia de un diagrama después de visualizarlo,Guardar la imagen actual de un diagrama de clases,Guardar la apariencia actual de un diagrama y recuperarla en el futuro,Realizar búsquedas por cualquier palabra clave que se muestre en un diagrama o árbol de clases,Utilizar la información sobre las herramientas para obtener todos los detalles de las clases, sus propiedades, métodos, parámetros, consultas y bloques xData,Visualizar el código de los métodos, consultas o bloques xData,Activar o desactivar la visualización de cualquiera de los elementos del diagrama, incluidos los iconos gráficosEn la siguiente imagen se puede ver cómo se visualizan las clases en Class Explorer, y así comprender mejor los conceptos mencionados en este artículo. Como ejemplo, veamos el paquete “Cinema” del namespace “SAMPLES”:Descripción general de las funcionesLa barra lateral izquierda contiene un árbol del paquete. Situando el cursor sobre el nombre del paquete y haciendo clic en un botón que aparece en el lado derecho se podrá visualizar el paquete completo. Si se selecciona la clase en el árbol del paquete se representará junto con sus clases vinculadas.Class Explorer puede mostrar varios tipos de dependencias entre las clases:Herencia. Se muestra con una flecha de color blanco que apunta hacia la dirección de la clase que se heredó;“Asociación” o relación entre las clases. Si un campo de alguna de las clases contiene una clase de otro tipo, el generador de diagramas lo mostrará como una relación de asociación;Relaciones padre-hijo y de uno a muchos: contienen las reglas para mantener la integridad de los datos.Si se sitúa el cursor sobre la relación, se resaltarán las propiedades establecidas en ella:Se debe tener en cuenta que Class Explorer no profundizará y no creará dependencias para las clases que se encuentran fuera del paquete actual. Únicamente mostrará las clases que se encuentran en el paquete actual, y si se necesita limitar la profundidad con que Class Explorer realice búsquedas para las clases, se debe utilizar la opción “Nivel de dependencia”:La clase en sí, se muestra como un recuadro que se divide en seis secciones:Nombre de la clase: si posiciona el cursor sobre el nombre de la clase, se podrá saber cuándo fue creada, sus modificaciones, ver los comentarios y todas las palabras clave que se asignaron a la clase. Al hacer doble clic sobre el encabezado de la clase se abrirá su documentación,Parámetros de la clase: todos los parámetros están asignados por tipo, palabras clave y comentarios. Los parámetros en cursivas, al igual que cualquier otra propiedad, contienen información sobre las herramientas y pueden desplazarse,Las propiedades de las clases son similares a las de los parámetros,Métodos: puede hacer clic sobre cualquiera de los métodos para ver su código fuente. La sintaxis de COS se resaltará,Consultas: son similares a los métodos, al hacer clic sobre ellos, se podrá ver su código fuente,Bloques xData: estos bloques contienen principalmente datos de tipo XML. Al hacer clic sobre ellos se mostrará el código fuente con formato en el bloqueDe manera predeterminada, cada clase se visualiza mediante una serie de iconos gráficos. El significado de cada icono puede determinarse al hacer clic en el botón Help que se encuentra en la esquina superior derecha de la pantalla. Si necesita una notación UML más o menos estricta que se muestra de forma predeterminada, así como la visualización de cualquiera de las secciones de la clase, se puede desactivar desde la sección Configuraciones.Si un diagrama es muy grande y no resulta familiar, se puede utilizar la función para buscar diagramas rápidamente. Se resaltarán las clases que contengan cualquier parte de la palabra clave introducida. Para avanzar a la siguiente coincidencia, se presiona Enter o se hace clic nuevamente en el botón de búsqueda:Finalmente, después de hacer todas las ediciones en el diagrama, se eliminarán todas las relaciones innecesarias y los elementos se colocarán en las posiciones correctas para lograr la apariencia deseada, se puede guardar al hacer clic en el botón "Download" que se encuentra en la esquina inferior izquierda: Cuando actives el botón del pin , se guardará la posición de los elementos que se encuentren en el diagrama del conjunto (o de un paquete) de clases actual. Por ejemplo, si selecciona las clases A y B, y después guarda la visualización con el botón del pin, verá exactamente la misma visualización cuando seleccione las clases A y B nuevamente, incluso después de reiniciar el navegador o el equipo. Pero si solamente selecciona la clase A, el diseño será el predeterminado.InstalaciónPara instalar Caché Class Explorer, solamente tendrás que importar la última versión XML del paquete en cualquier namespace. Cuando se complete la importación, notarás que aparece una nueva aplicación web llamada hostname/ClassExplorer/ (la barra que se encuentra al final de la ruta, es necesaria).Instrucciones detalladas sobre la instalaciónDescargar el archivo con la última versión de Caché Class Explorer,Descomprimir el archivo XML llamado Cache/CacheClassExplorer-vX.X.X.xml,Importar el paquete en cualquier namespace mediante alguna de las siguientes formas:Simplemente arrastrando el archivo XML hacia el Studio,Utilizando el Portal de administración del sistema: Explorador del sistema -> Clases -> Importar, y especifique la ruta hacia el archivo local,Utilizando el comando del terminal: do ##class(%Installer.Installer).InstallFromCommandLine(“Path/Installer.cls.xml”),Consultar el registro de importación, si todo se realizó correctamente, se podrá abrir la aplicación web en http://hostname/ClassExplorer/. Si algo salió mal, revisar lo siguiente:Si se tienen los permisos correctos para importar clases hacia este namespace,Si el usuario de la aplicación web tiene suficientes privilegios para acceder a diferentes namespaces,Si aparece el error 404, comprobar si agregó una "/" barra al final de la URL.Algunas capturas de pantalla adicionales[Captura de pantalla 1] Paquete DSVRDemo, desplazamiento del cursor sobre el nombre de la clase.[Captura de pantalla 2] Paquete DataMining, búsqueda de la palabra clave "TreeInput" en el diagrama.[Captura de pantalla 3] Visualización del código del método en la clase JavaDemo.JavaListSample.[Captura de pantalla 4] Visualización del contenido del bloque XData en la clase ClassExplorer.Router.Probad cómo funciona Class Explorer en el namespace estándar SAMPLES: demostración. Y aquí se muestra una evaluación en video del proyecto.Cualquier observación, sugerencia o comentario es bienvenido; podéis dejarlo aquí o en la sección Repositorio de GitHub.¡Espero que os resulte útil!
Artículo
Jose-Tomas Salvador · 14 ago, 2019
La funcionalidad de Sincronización de Objetos no es nueva, estaba presente en Caché, pero quería explorar un poco más en profundidad cómo funciona. Siempre he pensado que la sincronización automática de una base de datos es compleja en sí misma pero, para algunos escenarios muy particulares quizá no sea tan difícil. Así que he considerado un caso de uso muy simple (OK, quizá el caso típico, no descubro nada... pero si es común y funciona, es bueno ). Puedes bajar el código de GitHub y compilarlo en tu sistema, generar automáticamente datos de ejemplo y jugar un poco con ello. Está hecho para InterSystems IRIS pero debería funcionar también en las últimas versiones de Caché y Ensemble.Ahora vayamos al detalle. Mi aplicación de ejemplo, a nivel de clases (lo siento, no hay interfaz de usuario), considera un pequeño modelo de datos donde tenemos Items, Customers, Employees y Orders. Trabajando off-line, si somos comerciales, normalmente limitaremos nuestras operaciones a consultar: Items, Customers y/o Employess (por lo que esos datos los consideramos de solo-lectura); y a añadir o modificar Orders. El registro o modificación de Items, Customers o Employees lo podemos considerar como algo que debe hacerse en el sistema de base de datos MASTER y de ahí transmitido a los sistemas de base de datos CLIENT .Cuando definimos el modelo de clases, tenemos que tener en cuenta que transacciones queremos sincronizar (en nuestro caso Orders) y cuales no. En la definición de las clases debemos añadir Parameter OBJJOURNAL = 1; para indicar que el sistema tiene que mantener la relación de los objetos de dicha clase insertados/borrados/modificados. Igualmente, en el/los sistema(s) cliente, la creación de objetos sucederá en momentos diferentes y, si usamos IDKEYs por defecto, tendremos situaciones en las cuales el mismo objeto (tras la sincronización) tendrá un IDKEY diferente en cada base de datos... Como gestionamos eso? ... Necesitamos una forma de identificar global y univocamente un objeto entre bases de datos... y aquí es cuando el GUID viene en nuestra ayuda. InterSystems IRIS puede generar un ID global unico (Globally Unique ID) para un objeto que puede ser compartido entre sistemas IRIS y todos ellos pueden usarlo para decidir si están tratando o no con el mismo objeto. Hasta aquí bien. Para que una clase pueda generar automáticamente un GUID para cada nuevo objeto, tenemos que incluir Parameter GUIDENABLED = 1; en su definición. Y con esto, todo nuestro trabajo está hecho.En nuestro caso de uso tendremos algo similar a esto (la definición completa en GitHub...aquí recortada): Class SampleApps.Synch.Data.Order Extends (%Persistent,%Populate,%JSON.Adaptor){ /// We don't want to force other classes reference to use %JSON.Adaptor. Then we decide export the /// GUID of referenced objects (by default it will include the JSON of object referenced) Parameter %JSONREFERENCE As STRING [ Constraint = "OBJECT,ID,OID,GUID", Flags = ENUM ] = "GUID"; ///We'll keep track of this class for synchronization (assuming that in off-line mode is not ///allowed by the app to modify master classes Parameter OBJJOURNAL = 1; Parameter GUIDENABLED = 1; ...}Class SampleApps.Synch.Data.Customer Extends (%Persistent, %Populate){ ///This allows the class to be stored with the GUIDs ///Also is a class referenced in Order class which is to be synchronized, ///so this class objects need a GUID to be able to synchronize their references Parameter GUIDENABLED = 1; ...}Class SampleApps.Synch.Data.Item Extends (%Persistent, %Populate){ Parameter GUIDENABLED = 1; ...}Class SampleApps.Synch.Data.Employee Extends (%Persistent,%Populate){ Parameter GUIDENABLED = 1; ...} Como ves, hay una clase: Order; con OBJJOURNAL y GUIDENABLED, y las otras clases sólo tienen GUIDENABLED. ¿Por qué? Porque los objetos de esas clases son referenciadas dentro de cada Order y, aunque no mantenemos sus modificaciones, necesitamos saber que la misma Order referencia a los mismos objetos sin importar en que sistema(s) estemos mirando (IMPORTANTE: si no habilitamos GUID en los objetos referenciados, las Orders serán sincronizadas pero sin ninguna información relacionada a las referencias).OK. Dicho esto, puedes empezar a jugar. He implementado algunas utilidades en SampleApps.Synch.Util para generar datos y ejecutar operaciones básicas de interción/modificación/borrado. También encontrarás una API REST básica (SampleApps.Synch.API.v1.RestLegacy) para poder hacerlo desde un cliente REST o desde ObjectScript indiferentemente.Dispones de más información junto con todo el resto del código del proyecto aqui en GitHub. Puedes clonar el repositorio o descargar un zip con el código fuente. Una vez tengas el código en tu servidor, carga y compila la clase SampleApps.Synch.Config.Installer desde tu terminal (dentro del namespace que elijas), y ejecuta la instalación:TEST>do $system.OBJ.Load("c:/Temp/SampleApps/Synch/Config/Installer.cls","ck")TEST>set args("InstallingFromNS")="TEST"TEST>set args("NamespaceMaster")="CORE"TEST>set args("NamespaceClient")="NODE"TEST>do ##class(SampleApps.Synch.Config.Installer).setup(.args) La mayoría de los argumentos tienen valores por defecto (echa un vistazo a la clase SampleApps.Synch.Config.Installer, pero, como puedes ver en el ejemplo arriba, puedes cambiarlos antes de llamar al método setup).Tras su ejecución, tendrás 2 nuevos namespaces: CORE y NODE (MASTER y CLIENT por defecto si llamas a setup sin argumentos) con datos ya precargados en Orders, Items, Customers y Employees. Ambas bases de datos son idénticas en este punto. Puedes jugar con los servicios REST para cargar nuevos datos, preparar la sincronización de datos de un namespace y después sincronizarlos en el otro. Cualquier conflicto descubierto durante la sincronización será almacenado en SampleApps.Synch.Data.SynchConflict que también puede consultarse a través de un servicio REST (aparte de desde SQL).En GitHub he incluido más información y también ejemplos para llamar a servicios REST para que así puedas empezar a probar facilmente. Simplemente haz click aquí, descarga el código fuente o clone el repositorio y podrás estar probando en 2 minutos.Disfruta!!
Pregunta
Albert Forcadell · 5 mayo, 2023
hola, me es imposible hacer una consulta de forma correcta. he probado con clausulas LIMIT, OVER ... no válidas para Intersystems por lo visto. Tambien probe con HAVING , con TOP, ... incluso con GPT y otras AI, pero nada.
lo siento, pero mi sql no da para mas.
TABLA Comp.AlbLin
COLUMNAS AlbLin.ID , AlbLin.Description , AlbLin.Price , AlbLin.Date
Estoy peleando por una query que me calcule la MEDIA del campo precio AlbLin.Price pero solo de los ultimos/mas recientes 3 registros de fecha
---
i am not able to launch a right instruction in sql , please. LIMIT ... OVER ...no valid for Intersystems. i ve tried all . with HAVING, with TOP ,... paying for Ai and nothing.
my apologises , i am so limited.
TABLE Comp.AlbLin
COLUMNS AlbLin.ID , AlbLin.Description , AlbLin.Price , AlbLin.Date
i fight for a query to get the AVG average of AlbLin.Price for each AlbLin.ID taking only last/recent 3 rows AlbLin.Date
¡Hola Albert! Te agradecería que, para beneficio de todos los usuarios de la comunidad de desarrolladores en español, planteases la pregunta traducida al español si es posible.
Con respecto a tu pregunta, prueba con la siguiente query:
SELECT
a1.ID, AVG(a1.Price)
FROM Comp.AlbLin a1
WHERE a1."Date" in (SELECT TOP 3 a2."Date" FROM Comp.AlbLin a2 WHERE a1.ID = a2.ID ORDER BY a2."Date" DESC )
GROUP BY a1.ID order by a1.ID asc
Entiendo que el campo AlbLin.ID no es único por lo que indicas, por lo que podemos utilizar como criterio la fecha del dato. Te explico un poco la query:
Puedes ver como tenemos dentro del WHERE una subquery que nos extraerá las últimas 3 fechas para cada AlbLin.ID, serán las 3 últimas ya que hemos indicado TOP 3 de una query ordenada por fecha de forma descendiente, así que siempre serán las 3 últimas fechas.
En la SELECT principal hemos sacado el AlbLin.ID que nos servirá como criterio agrupador y hemos usado la función agrupadora AVG para AlbLin.Price.
En la instrucción GROUP BY hemos definido el campo agrupador AlbLin.ID y hemos añadido un ORDER BY, este último no es necesario.
Pues bien, la subquery nos devolverá las 3 últimas fechas que usaremos en la query principal para sólo utilizar aquellos registros relativos al AlbLin.ID que coincidan con esas fechas (la subquery usa dentro de su WHERE el identificador de la query principal).
Prueba la query y coméntanos el resultado.
¿Has podido probar la query que te comenté, Alberto? si, es correcta . y ademas bastante simple cuando las ves. lastima tener que molestar. muy agradecido por la aportacion. es relativamente sencilla , 😅
he intentado ir un poco mas alla , y mejorarla o mas bien complicarla. y he vuelto a ser incapaz de ubicar bien los case when para que funcione.
queria conseguir que si la fecha mas reciente tiene mas de quince dias " ... (a1.FechaLinea > DATE(CURRENT_DATE-15)) ..." solo coja las 2 ultimas fechas . o sea que en lugar de un TOP 3 , sea un TOP 2.
he probado con los CASE WHEN dentro del select y fuera cambiando la instruccion pero no consigo que funcione.
de todas formas , la solucion ofrecida es para mi un gran aporte y cubre casi la totalidad de casos de la consulta. muchas gracias. si , si . acabo de reportar. ¡Nunca molestan vuestras preguntas, Albert! Al revés... gracias por preguntar, para eso estamos, y encantados de poder ayudar :D Pues solo tienes que meter la condición de la subquery entre paréntesis y añadir un And con la condición de la fecha a modo de:
WHERE (date>X AND subquery top 2) OR (date <=X AND subquery top 3) tambien funciona... 😁 . y yo dale que te pego con los CASE. ...
voy a ir desarrollar un poco mas la consulta , a ver si discurro algo mas y no hace falta vuestra atencion. ( seguro que vuelvo , jaja)
vaya ... un placer y muy agradecido de me hayais atendido las consultas tan rapido. ... y tan eficaces.
p.d.
dejo la sentencia completa como ejemplo por si a alguien le sirve de modelo
v.0
SELECT a1.Articulo, a1.DescArticulo, AVG(a1.PrecioCoste)FROM Comp.AlbaranLin a1WHERE a1.FechaLinea in (SELECT TOP 3 a2.FechaLinea FROM Comp.AlbaranLin a2 WHERE a1.Articulo = a2.Articulo ORDER BY a2.FechaLinea DESC ) (*opcional *AND a1.Articulo = '337' AND a1.FechaLinea > DATE(CURRENT_DATE-15) *)GROUP BY a1.Articulo order by a1.Articulo asc ;
v.1
SELECT a1.Articulo, a1.DescArticulo, AVG (a1.PrecioCoste)FROM Comp.AlbaranLin a1WHERE (a1.FechaLinea in (SELECT TOP 3 a2.FechaLinea FROM Comp.AlbaranLin a2 WHERE a1.Articulo = a2.Articulo ORDER BY a2.FechaLinea DESC ) AND a1.Articulo = '337' AND a1.FechaLinea >= DATE(CURRENT_DATE-15))OR(a1.FechaLinea in (SELECT TOP 2 a2.FechaLinea FROM Comp.AlbaranLin a2 WHERE a1.Articulo = a2.Articulo ORDER BY a2.FechaLinea DESC ) AND a1.Articulo = '337' AND a1.FechaLinea < DATE(CURRENT_DATE-15))GROUP BY a1.Articulo order by a1.Articulo asc ; Genial Albert, ¡muchas gracias! Y no te preocupes, para eso estamos. Puedes preguntar todo lo que necesites.
Artículo
Ricardo Paiva · 18 mar, 2021
Demo lista para usar de un servidor FHIR con IRIS for Health 2020.2:
* Transformación HL7v2 al servidor FHIR
* Servidor FHIR que se puede consultar en SQL

### Instalación
Clona este repositorio
```
git clone https://github.com/grongierisc/FHIR-HL7v2-SQL-Demo.git
```
Docker
```
docker-compose up --build -d
```
### Uso
* Puedes utilizar la configuración de postman en misc/fhirhl7v2demo.postman_collection.json
* Utiliza UX en http://localhost:4201
* ***Inicio de sesión/Contraseña***: SuperUser/password
### Cómo utilizar la demostración

3 pasos para utilizarla:
## Importar mensajes HL7v2
Haz clic en la flecha izquierda que está entre IRIS y la ambulancia.
Esto abre las siguientes ventanas:

Desde aquí se pueden importar muestras desde este directorio en el repositorio de Git:
sampleFiles
Elige uno y haz clic en enviar.

Desde aquí puedes hacer clic en Message Trace:

Selecciona el primero:

Aquí puedes ver la transformación preparada entre HL7v2, SDA y FHIR.
## Utiliza el cliente FHIR
Haz clic en la flecha entre IRIS y el FHIR client:

El pequeño swagger te da la oportunidad de consultar en FHIR el repositorio lleno desde el mensaje HL7v2 o desde el FHIR client.
Por ejemplo :

## Utiliza el cliente SQL
Haz clic en la flecha que está entre IRIS y SQL client:

Desde aquí se pueden ver todos los recursos FHIR en una estructura relacional de SQL. Debe quedar claro que esta estructura SQL puede cambiar sin previo aviso. Dicha estructura no está documentada y su uso no tiene el respaldo de InterSystems.
Artículo
Ricardo Paiva · 4 mayo, 2023
En los últimos años, las tecnologías de inteligencia artificial para la generación de texto han avanzado significativamente. Por ejemplo, los modelos de generación de texto basados en redes neuronales pueden producir textos que son casi indistinguibles de los textos escritos por humanos. ChatGPT es uno de estos servicios. Es una enorme red neuronal entrenada con una gran cantidad de textos, que puede generar textos sobre varios temas y adaptarse a un contexto dado.
La nueva tarea para las personas es desarrollar formas de reconocer textos escritos no solo por personas sino también por inteligencia artificial (IA). Esto se debe a que, en los últimos años, los modelos de generación de texto basados en redes neuronales se han vuelto capaces de producir textos que son casi indistinguibles de los textos escritos por humanos.
Hay dos métodos principales para el reconocimiento de texto escrito por inteligencia artificial (IA):
Utilizar algoritmos de machine learning para analizar las características estadísticas del texto;
Utilizar métodos criptográficos que pueden ayudar a determinar la autoría del texto
En general, la tarea de reconocimiento de texto de IA es difícil pero importante.
Me complace presentar una aplicación para el reconocimiento de textos generados por inteligencia artificial (IA). Durante el desarrollo, aproveché los beneficios de InterSystems Cloud SQL e Integrated ML, que incluyen:
Solicitudes de datos rápidas y eficientes, con alto rendimiento y velocidad;
Interfaz amigable para usuarios no expertos en bases de datos y machine learning;
Escalabilidad y flexibilidad para ajustar rápidamente los modelos de ML según los requisitos;
En el desarrollo y entrenamiento posterior del modelo, utilicé un conjunto de datos abierto, concretamente 35 mil textos escritos. La mitad de los textos fueron escritos a mano por un gran número de autores, y la otra mitad fue generada por IA con ChatGPT.
Configuración usada para el modelo GPT:
model="text-curie-001"
temperature=0.7
max_tokens=300
top_p=1
frequency_penalty=0.4
presence_penalty=0.1
A continuación, se establecieron unos 20 parámetros básicos, según los cuales se llevó a cabo el entrenamiento posterior. Estas son algunas de las opciones que utilicé:
Cantidad de caracteres
Cantidad de palabras
Longitud media de las palabras
Cantidad de frases
Longitud media de las frases
Cantidad de palabras únicas
Cantidad de palabras vacías (stop words)
Ratio de palabras únicas
Cantidad de signos de puntuación
Ratio de signos de puntuación
Cantidad de preguntas
Cantidad de exclamaciones
Cantidad de dígitos
Cantidad de letras en mayúscula
Cantidad de palabras repetidas
Cantidad de bigramas únicos
Cantidad de trigramas únicos
Cantidad de cuatrigramas únicos
Como resultado, obtuve una sencilla aplicación que podéis usar para vuestras tareas o para pasarlo bien.
Así es como se ve:
Para probar la aplicación podéis usar la demo online o ejecutarla en local con vuestra cuenta Cloud SQL.
Todos los comentarios sobre la app son bienvenidos!
Anuncio
Esther Sanchez · 25 mar, 2021
¡Hola Comunidad!
En esta publicación, os explicamos las distintas Insignias de Global Masters y qué hay que hacer para conseguirlas.
Información general sobre Niveles e Insignias de Global Masters
Todos los miembros de Global Masters empiezan en el 1er nivel ("Insider"), cuando se registran en el Programa de Fidelización. Para subir de nivel, hay que ganar un número de insignias del siguiente nivel. Las insignias se ganan realizando diferentes "retos".¿Cómo puedes saber en qué nivel estás y las insignias que tienes? Sigue estos sencillos pasos:
1. En la página de inicio de Global Masters, haz clic en la foto de tu perfil, en la parte superior derecha > después, haz clic en tu nombre2. Ahí ya puedes ver en qué nivel estás, las insignias que has ganado y lo que te falta para pasar al siguiente nivel3. Si haces clic en "See available badges" verás todas las insignias y niveles del programa
También puedes ver tus insignias ganadas en tu página de perfil en la Comunidad de Desarrolladores.
Cómo conseguir las insignias en GM
Nombre de la insignia
Reglas
Insignias por número de vistas
Popular Writer - 750 vistas
Insignias conseguidas si cualquiera de tus publicaciones (preguntas o artículos) en la Comunidad de Desarrolladores consiguen más de 750 / 2 000 / 5 000 vistas únicas.
La publicación no debe ser eliminada; tiene que ser publicada.
Solo cuentan las publicaciones con una calificación positiva.
No cuentan las publicaciones con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
Cada insignia solo se concede una vez. Los puntos se dan por cada publicación que consigue el número de vistas indicadas.
Notable Writer - 2 000 vistas
Famous Writer - 5 000 vistas
Gold Writer - 15 000 vistas
Insignias por artículos publicados
Reporter - 5 artículos
Insignias conseguidas cuando llegas a 5 / 10 / 25 / 50 artículos (no preguntas) publicados en la Comunidad.
Las publicaciones no deben ser eliminadas; tienen que ser publicadas.
Solo cuentan las publicaciones con una calificación positiva.
No cuentan las publicaciones con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
Blogger - 10 artículos
Influencer - 25 artículos
Opinion Maker - 50 artículos
DC Best Practices Author Badge - 1 best practice
Insignias conseguidas cuando llegas a 1 / 10 / 25 / 50 artículos (no preguntas) considerados como Best Practice ("Mejores prácticas") en la Comunidad de Desarrolladores.
Las publicaciones no deben ser eliminadas; tienen que ser publicadas.
Solo cuentan las publicaciones con una calificación positiva.
No cuentan las publicaciones con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
RecognizableBest Practices Author Badge - 2 best practices
Bronze Best Practices Author Badge - 3 best practices
Silver Best Practices Author Badge- 4 best practices
Gold Best Practices Author Badge - 5 best practices
Master of Answers - 5 respuestas aceptadas
Insignias conseguidas cuando tus respuestas en la Comunidad de Desarrolladores son marcadas 5 / 10 / 25 / 50 veces como respuestas aceptadas.
Bronze Master of Answers - 10 respuestas aceptadas
Silver Master of Answers - 25 respuestas aceptadas
Gold Master of Answers - 50 respuestas aceptadas
Insignias por preguntas
Curious Member - 5 preguntas
Insignias conseguidas cuando llegas a 5 / 10 / 25 / 50 preguntas en la Comunidad de Desarrolladores.
Las preguntas no deben ser eliminadas; tienen que ser publicadas.
Solo cuentan las preguntas con una calificación positiva.
No cuentan las preguntas con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
Thorough Member - 10 preguntas
Inquisitive Member - 25 preguntas
Socratic Member - 50 preguntas
Insignias por favoritos
Favorite Post - 10 veces
Insignias conseguidas cuando tus publicaciones (preguntas o artículos) en la Comunidad de Desarrolladores, son marcadas 10 / 50 / 100 veces como favoritas.
Las publicaciones no deben ser eliminadas; tienen que ser publicadas.
Solo cuentan las publicaciones con una calificación positiva.
No cuentan las preguntas con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
Remarkable Post - 50 veces
Unforgettable Post - 100 veces
Insignias por votos
Insightful Author - 50 votos
Insignias conseguidas cuando tus publicaciones (preguntas o artículos) en la Comunidad de Desarrolladores, consiguen 50 / 100 / 500 / 1 000 votos.
Las publicaciones no deben ser eliminadas; tienen que ser publicadas.
No cuentan las publicaciones con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
Expert Author - 100 votos
Recognizable Author - 500 votos
Powerful Author - 1000 votos
Insightful Commenter - 50 votos
Insignias conseguidas cuando tus respuestas (comentarios a preguntas) en la Comunidad de Desarrolladores, consiguen 50 / 100 / 500 / 1 000 votos.
No cuentan las respuestas eliminadas
No cuentan las respuestas con la etiqueta Feedback sobre la Comunidad de Desarrolladores .
Expert Commenter - 100 votos
Recognizable Commenter - 500 votos
Powerful Commenter - 1 000 votos
DC Moderator
Concedida a los Moderadores de la Comunidad de Desarrolladores. Esta insignia no está relacionada con los niveles.
Insignias anuales - Top 10 Autores
Gold Best-Selling Author - 1er puesto
1º / 2º / 3º / 4º-10º puestos en la categoría "DC Best-Selling Author".
Autores cuyos artículos consiguieron el mayor número de visualizaciones en la Comunidad de Desarrolladores durante un año.
Silver Best-Selling Author - 2º puesto
Bronze Best-Selling Author - 3er puesto
DC Best-Selling Author - 4º-10º puestos
Gold Expert - 1er puesto
1º / 2º/ 3º / 4º-10º puestos en la categoría “DC Expert”.
Autores que consiguieron el mayor número de "Respuestas aceptadas" en la Comunidad de Desarrolladores durante un año.
Silver Expert - 2º puesto
Bronze Expert - 3er puesto
DC Expert - 4º-10º puestos
Gold Opinion Leader - 1er puesto
1º / 2º/ 3º / 4º-10º puestos en la categoría “DC Opinion Leader”.
Autores cuyas publicaciones y respuestas obtuvieron el mayor número de votos en la Comunidad de Desarrolladores durante un año.
Silver Opinion Leader - 2º puesto
Bronze Opinion Leader - 3er puesto
DC Opinion Leader - 4º-10º puestos
Insignias por recomendaciones
Gold Recruiter - 100 recomendaciones
Insignias conseguidas cuando se unen a la Comunidad de Desarrolladores 1 /10 / 50 / 100 personas a las que recomendaste la Comunidad.
Silver Recruiter - 50 recomendaciones
Bronze Recruiter - 10 recomendaciones
DC Recruiter - 1 recomendación
Insignias por Contribuciones Básicas
DC Author
Insignia conseguida cuando publicas tu primer artículo en la Comunidad de Desarrolladores.
La publicación no debe ser eliminada; tiene que ser publicada.
No cuentan los artículos con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
Debe ser una publicación del tipo "Artículo".
InterSystems Researcher
Insignia conseguida cuando publicas tu primera pregunta en la Comunidad de Desarrolladores.
La pregunta no debe ser eliminada; tiene que ser publicada.
No cuentan las preguntas con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
Debe ser una publicación del tipo "Pregunta".
DC Commenter
Insignia conseguida cuando publicas tu primer comentario en la Comunidad de Desarrolladores.
Comentario con algún "Me gusta" o sin ningún "Me gusta"
No cuentan los comentarios realizados con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
DC Problem Solver
Insignia conseguida cuando tu respuesta a la pregunta de alguien es marcada como "Respuesta aceptada" en la Comunidad de Desarrolladores.
La respuesta tiene que ser marcada como "Respuesta aceptada"
No cuentan las respuestas realizadas con la etiqueta Feedback sobre la Comunidad de Desarrolladores.
DC Translator
Insignia conseguida cuando publicas tu primera traducción en la Comunidad de Desarrolladores. Cómo añadir una traducción
Winner of Advent of Code
Insignia concedida a los ganadores del concurso "Advent of Code". Mas info aquí.
Global Master of the Month
Insignia concedida a los "Advocate of the Month" en Global Masters.
Gold Advocate of the Year
Insignias concedidas a los "Best Advocates of the Year" en Global Masters.
Silver Advocate of the Year
Bronze Advocate of the Year
Insignias de Open Exchange
InterSystems Open Exchange Developer
Insignias conseguidas cuando publicas 1 / 5 / 10 / 25 aplicaciones en InterSystems Open Exchange.
Bronze Open Exchange Developer
Silver Open Exchange Developer
Gold Open Exchange Developer
Además...
Consulta la información adicional sobre Global Masters:
Cómo unirse a Global Masters
Descripción de los Niveles de Global Masters
Si tienes alguna duda sobre las Insignias, puedes dejarnos un comentario en esta publicación y te responderemos al momento!
Artículo
Alberto Fuentes · 17 abr, 2019
El archivo events_examples.zip contiene dos ejemplos que muestran cómo procesar una carga de trabajo de forma asíncrona utilizando colas persistentes.Events_Simple.prj.xmlEvents_PubSub.prj.xml (actualizado! este ejemplo se ha publicado en https://github.com/intersystems-ib/cache-iat-pubsub)Events SimpleEste es un ejemplo muy sencillo que crea algunos procesos trabajadores y les encola mensajes utilizando $system.Event.
; crear un recurso compartido y crear los procesos trabajadores
USER>do ##class(IAT.S04.Event.Test).Setup()
; encolar algunos mensajes hacia los trabajadores y ver qué sucede
USER>do ##class(IAT.S04.Event.Test).Run()
Show log? no/[yes]:
^Samples.Log=10
^Samples.Log(1)="[2016-02-19 09:43:14] Enqueuing 1"
^Samples.Log(2)="[2016-02-19 09:43:14] Worker 8168 grabs: 1"
^Samples.Log(3)="[2016-02-19 09:43:14] Enqueuing 2"
^Samples.Log(4)="[2016-02-19 09:43:14] Worker 18184 grabs: 2"
^Samples.Log(5)="[2016-02-19 09:43:14] Enqueuing 3"
^Samples.Log(6)="[2016-02-19 09:43:14] Worker 8168 grabs: 3"
^Samples.Log(7)="[2016-02-19 09:43:14] Enqueuing 4"
^Samples.Log(8)="[2016-02-19 09:43:14] Worker 18184 grabs: 4"
^Samples.Log(9)="[2016-02-19 09:43:14] Enqueuing 5"
^Samples.Log(10)="[2016-02-19 09:43:14] Worker 8168 grabs: 5"
; trabajo terminado, podemos enviar más mensajes o matar a los procesos trabajadores
write $system.Process.Terminate(8168)
1
write $system.Process.Terminate(18184)
1
Clases:
Manager - métodos para crear recursos compartidos así como los procesos trabajadores y encolar mensajes.Queue - clase persistente simple utilizada para almacenar mensajes.Worker - representa a un trabajador que espera que le llegue un evento para procesar el mensaje recibido.
Events PubSub
Este ejemplo está construido sobre la misma base que Events_Simple.
El objetivo en este caso es construir un modelo sencillo de Publicador-Subscriptor.
Hay dos subscriptores para dos tipos de mensajes distintos:
SubPatient - gestiona los mensajes relacionados con pacientes.SubDummy - gestiona mensajes dummys.
; crear los eventos y los procesos subscriptores
do ##class(IAT.S05.PubSub.Example.Main).Setup()
; enviar algunos mensajes (de los dos tipos) al canal
do ##class(IAT.S05.PubSub.Example.Main).Run()
; mostrar el log con el resultado de lo que ha sucedido
zw ^PubSub.Log
Log
Clases
Hola Alberto!¡Qué buen artículo!Puedes a publicar el ejemplo en Open Exhcange tambien?
Artículo
Kurro Lopez · 20 abr, 2020
Aqui teneis una clase "test" con el código para envíar un correo electrónico en formato HTML con una imagen incrustada.
Edita el texto para cambiar la imagen incrustada, dirección de destino y remitente, asunto, contenido, etc...
Class objectscript.sendEmailWithImage Extends %RegisteredObject
{
classmethod test() {
S SmtpServer = ""
S SmtpUserName = ""
S SmtpPassword = ""
S imgPath="C:\test.jpg"
set s=##class(%Net.SMTP).%New()
set s.smtpserver=SmtpServer
set auth=##class(%Net.Authenticator).%New() ; use default authentication list
set auth.UserName=SmtpUserName
set auth.Password=SmtpPassword
set s.authenticator=auth
Set objMail=##class(%Net.MailMessage).%New()
Set objMail.From="sender@testhost.com"
Do objMail.To.Insert("reciever@testhost.com")
Set objMail.Subject="Test-Email"
Set objMail.Charset="iso-8859-1"
Set obj1 =objMail
Set obj1.IsHTML=1
Set obj1.IsBinary = 0
Set obj1.IsMultiPart = 1
Set obj1.MultiPartType ="related"
Do obj1.Headers.SetAt("inline","Content-Disposition")
//alternative container for the text-parts
#dim textbody as %Net.MailMessagePart
s textbody = obj1.AttachNewMessage()
s textbody.IsMultiPart=1
s textbody.IsHTML=0
s textbody.MultiPartType="alternative"
//html part
#dim text as %Net.MailMessagePart
//text part
#dim texttxt as %Net.MailMessagePart
s texttxt = textbody.AttachNewMessage()
//s texttxt.ContentType="text/plain"
d texttxt.TextData.Write("this is plain text")
s text = textbody.AttachNewMessage()
s text.IsHTML=1
s text.IsBinary=0
s text.IsMultiPart=0
Do text.TextData.Write("<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"">")
do text.TextData.Write("<html><head><meta http-equiv=""content-type"" content=""text/html; charset=ISO-8859-1"">")
Do text.TextData.Write("</head><body text=""#000000"" bgcolor=""#ffffff"">")
Do text.TextData.Write("Das ist ein Test in html")
Do text.TextData.Write("<img src=""cid:test.jpg"" />")
Do text.TextData.Write("</body></html>")
// Image Message Part
#dim obj2 as %Net.MailMessagePart
Set obj2 = obj1.AttachNewMessage()
Set obj2.IsBinary = 1
Set obj2.IsMultiPart = 0
Set obj2.FileName="test.jpg"
Do obj2.BinaryData.LinkToFile(imgPath)
Do obj2.Headers.SetAt("inline","Content-Disposition")
Do obj2.Headers.SetAt("<test.jpg>","Content-ID")
set status=s.Send(objMail)
d $system.OBJ.DisplayError(status)
w status,!
}
}
Aquí tienes el enlace para ver el código en GitHub: https://github.com/intersystems-community/code-snippets/blob/master/src/cls/objectscript/sendEmailWithImage.cls
Artículo
Alberto Fuentes · 8 jun, 2021
Otro artículo sobre "Trucos y consejos de VSCode" -
.png)
¿Quieres ver esta opción en VSCode?
Esta vez nos centraremos en cómo obtener el Asistente SOAP (*SOAP Wizard*) tal y como estaba disponible en Studio — para definir un cliente de servicio web SOAP basado en WSDL (y *Business Operation*), o servicio —.
Si trabajas con Servicios web (*Web services*), lo más probable es que hayas utilizado el Asistente SOAP en Studio. Lo abrirías en *Tools > Add-Ins*:
.png)
Y este abría una "*Server Template*":
.png)
En VSCode, puede que te preguntes cómo puedes acceder a eso.
Bueno, el hecho básico que hay que comprender es que realmente este complemento o asistente es simplemente una página web, que se muestra en Studio como hemos visto anteriormente y, como tal, también se puede acceder a ella desde un simple navegador. VSCode facilita la apertura de dicho navegador con el contenido deseado (construyendo la URL correcta con el nombre del servidor, el puerto, la aplicación web, etc.).
El resultado sería el mismo que ver una opción para abrir el Portal de administración o la Referencia de clase (con las URLs correspondientes) al hacer clic en la Conexión del servidor sobre la barra de estado inferior de VSCode, por ejemplo:
.png)
También verás una entrada para el Asistente SOAP.
Puedes conseguir esto al añadir una entrada 'links' a tu objeto 'conn' que se encuentra en tu configuración de JSON de tu extensión ObjectScript, y especificando la URL deseada (utilizando las variables correspondientes).
Esto se mencionó en un debate sobre Problemas con VSCode que se encuentra en el GitHub VSCode ObjectScript, como [problema "Asistente SOAP"](https://github.com/intersystems-community/vscode-objectscript/issues/325), con comentarios de @John Murray y @Ondřej Hoferek, y también se menciona en esta respuesta de @Timothy Leavitt a una pregunta de la Comunidad.
El valor JSON sería:
"SOAP Wizard": "${serverUrl}/isc/studio/templates/%25ZEN.Template.AddInWizard.SOAPWizard.cls?Namespace=${namespace}${serverAuth}"
Y esta parte se vería así:
.png)
Una vez que tengas esto, verás una opción adicional cuando hagas clic en la Conexión -
.png)
Y al elegir esa opción accederás al esperado asistente (abierto en un navegador):
.png)
Os dejo un breve GIF mostrando este proceso (comienza por el menú normal al hacer clic en la Conexión, y termina con el menú que incluye el Asistente SOAP).

Fíjate que hay otros asistentes (o plantillas) que puedes añadir de esta manera (como el Asistente XSD, por ejemplo).
Excelente consejo, tanto para abrir este wizard como el resto de asistentes, poco a poco el VSCode va cogiendo forma. ¡Muchas gracias Alberto! Hay que potenciar el VSCode.
Artículo
Eduardo Anglada · 25 mayo, 2021
¡Hola Comunidad!
ObjectScript, el lenguaje de InterSystems IRIS, tiene la capacidad de extender clases utilizando una funcionalidad muy interesante llamada XData.
Es una sección en tu clase que puede ser usada para crear definiciones personalizadas, para utilizarlas dentro de la clase misma o externamente.
Crear una o más definiciones XData para tu clase es muy sencillo, mira el ejemplo:
Class dc.Sample.Person Extends (%Persistent, %JSON.Adaptor, %Populate)
{
Property Name As %VarString;
Property Title As %String;
Property Company As %String;
Property Phone As %VarString;
Property DOB As %Date(MAXVAL = "$piece($horolog, "","", 1)");
/// Index for property DOB
Index DOBIndex On DOB;
ClassMethod AddTestData(amount As %Integer = 10)
{
d ..Populate(amount)
}
/// Documentation for Person
XData PersonDocHtml [ MimeType = text/html ]
{
<h1>This is the Person class</h1>
}
XData PersonDocMarkdown [ MimeType = text/markdown ]
{
<h1>This is the Person class</h1>
}
Ten en cuenta que tras definir los métodos, solo tienes que añadir una o más secciones XData con tres subsecciones: XData NomeSecaoXData [MimeType = TypeOfMimeType]. El contenido se pone entre corchetes.
Todos los elementos XData se almacenan en la clase persistente % Dictionary.XDataDefinition. Esto significa que es posible recuperar las definiciones usando lenguaje SQL, internamente o externamente. Mira el ejemplo:
Class dc.mkdocs.Generator
{
ClassMethod Generate()
{
Set qry = "SELECT parent, Name, Description FROM %Dictionary.XDataDefinition WHERE MimeType IN ('text/markdown','text/html')"
Set stm = ##class(%SQL.Statement).%New()
Set qStatus = stm.%Prepare(qry)
If qStatus'=1 {Write "%Prepare failed:" Do $System.Status.DisplayError(qStatus) Quit}
Set rset = stm.%Execute()
While rset.%Next() {
Write "Row count ",rset.%ROWCOUNT,!
Write rset.parent
Write ": ",rset.Description,!
Write ..GetXDataContent(rset.parent,rset.Name),!!
}
Write !,"Total row count=",rset.%ROWCOUNT
}
ClassMethod GetXDataContent(className, xdataName) As %String
{
set content = ""
for i=1:1:$$$comMemberKeyGet(className,$$$cCLASSxdata,xdataName,$$$cXDATAdata) {
set content = content_$$$comMemberArrayGet(className,$$$cCLASSxdata,xdataName,$$$cXDATAdata,i)
}
quit content
}
}
En este ejemplo, todos los elementos XData con Mime Type markdown y html son recuperados y se imprime tanto el nombre de la clase en la que se localiza el elemento XData como su descripción. Si quieres recuperar el contenido del elemento XData consulta GetXDataContent (gracias @Eduard.Lebedyuk).
Es una funcionalidad muy interesante, ya que podemos catalogar la documentación de todas las clases de una aplicación y tener un fácil acceso a ellas. ¡Genial!
Anuncio
Ricardo Paiva · 18 mar, 2022
# Iris Healthtoolkit Service
[](https://youtu.be/lr2B7zSFkds "Video")
Fácil de usar HL7v2 a FHIR, CDA a FHIR, FHIR a HL7v2 como un Servicio.
El objetivo de este proyecto es ofrecer una API REST que pueda convertir fácilmente varios formatos de salud.
Publica el formato deseado en el cuerpo REST, obtén la respuesta en el nuevo formato.
*  SaaS Offer : https://aws.amazon.com/marketplace/pp/prodview-q7ryewpz75cq2 
*  Video : https://youtu.be/lr2B7zSFkds 
## Instalación
Clona este repositorio
```
git clone https://github.com/grongierisc/iris-healthtoolkit-service.git
```
Docker
```
docker-compose up --build -d
```
## Uso
* Ve a: http://localhost:32783/swagger-ui/index.html
## Detalles de la API
* HL7 a FHIR
```
POST http://localhost:32783/api/hl7/fhir
```
* FHIR a HL7 ADT
```
POST http://localhost:32783/api/fhir/hl7/adt
```
* FHIR a HL7 ORU
```
POST http://localhost:32783/api/fhir/hl7/oru
```
* FHIR a HL7 vxu
```
POST http://localhost:32783/api/fhir/hl7/vxu
```
* CDA a FHIR
```
POST http://localhost:32783/api/cda/fhir
```
* FHIR repo
```
GET http://localhost:32783/api/fhir/metadata
```
## Formatos de entrada de HL7 compatibles:
* ADT_A01, ADT_A02, ADT_A03, ADT_A04, ADT_A05, ADT_A06, ADT_A07, ADT_A08, ADT_A09, ADT_A10, ADT_A11, ADT_A12, ADT_A13, ADT_A17, ADT_A18, ADT_A23, ADT_A25, ADT_A27, ADT_A28, ADT_A29, ADT_A30, ADT_A31, ADT_A34, ADT_A36, ADT_A39, ADT_A40, ADT_A41, ADT_A45, ADT_A47, ADT_A49, ADT_A50, ADT_A51, ADT_A60
* BAR_P12
* MDM_T02, MDM_T04, MDM_T08, MDM_T11
* OMP_O09
* ORM_O01
* ORU_R01
* PPR_PC1, PPR_PC2, PPR_PC3
* RDE_O11
* SIU_S12, SIU_S13, SIU_S14, SIU_S15, SIU_S16, SIU_S17, SIU_S26
* VXU_V04
## Cómo funciona
El proyecto funciona con el diagrama dinámico: SDA.
El SDA (Summary Document Architecture) es el Formato de Datos Clínicos de InterSystems.
Las correspondencias SDA FHIR se pueden consultar [aquí](https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=HXFHIR_transforms), y las de CDA -> SDA [aquí](https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=HXCDA).

Artículo
Ricardo Paiva · 29 ene, 2021
¡Hola Desarroladores!
IRIS External Table es un proyecto de código abierto de la comunidad de InterSystems, que permite utilizar archivos almacenados en el sistema de archivos local y almacenar objetos en la nube como AWS S3 y tablas SQL. 
Se puede encontrar en GitHub Open Exchange y está incluido en el administrador de paquetes InterSystems Package Manager (ZPM).
Para instalar External Table desde GitHub, utilice:
git clone https://github.com/antonum/IRIS-ExternalTable.git
iris session iris
USER>set sc = ##class(%SYSTEM.OBJ).LoadDir("/IRIS-ExternalTable/src", "ck",,1)
Para instalarlo con el ZPM Package Manager, utilice:
USER>zpm "install external-table"
## Cómo trabajar con archivos locales
Crearemos un archivo simple que tiene este aspecto:
a1,b1
a2,b2
Abra su editor favorito y cree el archivo o utilice solo una línea de comandos en Linux/Mac:
echo $'a1,b1\na2,b2' > /tmp/test.txt
Cree una tabla SQL en IRIS para representar este archivo:
create table test (col1 char(10),col2 char(10))
Convierta la tabla para utilizar el almacenamiento externo:
CALL EXT.ConvertToExternal(
'test',
'{
"adapter":"EXT.LocalFile",
"location":"/tmp/test.txt",
"delimiter": ","
}')
Y finalmente, consulte la tabla:
select * from test
Si todo funciona según lo previsto, debería ver el resultado de la siguiente forma:
col1 col2
a1 b1
a2 b2
Ahora regrese al editor, modifique el contenido del archivo y ejecute nuevamente la consulta SQL. ¡¡¡Tarán!!! Está leyendo nuevos valores de su archivo local en SQL.
col1 col2
a1 b1
a2 b99
## Cómo leer los datos desde S3
En puede acceder a los datos de la COVID que se actualizan constantemente, estos se almacenan por AWS en el lago de datos públicos.
Intentaremos acceder a una de las fuentes de datos en este lago de datos: `s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states`
Si tiene instalada la herramienta de línea de comandos para AWS, puede repetir los siguientes pasos. Si no es así, vaya directamente a la parte de SQL. No es necesario que tenga ningún componente específico de AWS instalado en su equipo para continuar con la parte de SQL.
$ aws s3 ls s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/
2020-12-04 17:19:10 510572 us-states.csv
$ aws s3 cp s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv .
download: s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv to ./us-states.csv
$ head us-states.csv
date,state,fips,cases,deaths
2020-01-21,Washington,53,1,0
2020-01-22,Washington,53,1,0
2020-01-23,Washington,53,1,0
2020-01-24,Illinois,17,1,0
2020-01-24,Washington,53,1,0
2020-01-25,California,06,1,0
2020-01-25,Illinois,17,1,0
2020-01-25,Washington,53,1,0
2020-01-26,Arizona,04,1,0
Por lo tanto, tenemos un archivo con una estructura bastante simple y cinco campos delimitados.
Para mostrar esta carpeta S3 como en External Table, primero necesitamos crear una tabla “regular” con la estructura deseada:
-- create external table
create table covid_by_state (
"date" DATE,
"state" VARCHAR(20),
fips INT,
cases INT,
deaths INT
)
Tenga en cuenta que algunos campos de datos como “Date” son palabras reservadas en el SQL de IRIS y deben escribirse entre comillas dobles. Entonces, necesitamos convertir esta tabla “regular” en la tabla “externa”, basada en el bucket AWS S3 y con el tipo CSV.
-- convert table to external storage
call EXT.ConvertToExternal(
'covid_by_state',
'{
"adapter":"EXT.AWSS3",
"location":"s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/",
"type": "csv",
"delimiter": ",",
"skipHeaders": 1
}'
)
Si observa detenidamente, en EXT.ExternalTable los argumentos de los procedimientos son el nombre de la tabla y luego la cadena JSON, además contiene varios parámetros como la ubicación para buscar archivos, el adaptador para utilizarlos, un delimitador, etc. Además, External Table de AWS S3 es compatible con el almacenamiento de Azure BLOB, Google Cloud Buckets y el sistema de archivos local. El repositorio de GitHub contiene referencias para la sintaxis y opciones que son compatibles con todos los formatos.
Y finalmente, consulte la tabla:
-- query the table
select top 10 * from covid_by_state order by "date" desc
[SQL]USER>>select top 10 * from covid_by_state order by "date" desc
2. select top 10 * from covid_by_state order by "date" desc
date state fips cases deaths
2020-12-06 Alabama 01 269877 3889
2020-12-06 Alaska 02 36847 136
2020-12-06 Arizona 04 364276 6950
2020-12-06 Arkansas 05 170924 2660
2020-12-06 California 06 1371940 19937
2020-12-06 Colorado 08 262460 3437
2020-12-06 Connecticut 09 127715 5146
2020-12-06 Delaware 10 39912 793
2020-12-06 District of Columbia 11 23136 697
2020-12-06 Florida 12 1058066 19176
Es comprensible que se necesite más tiempo para consultar los datos de la tabla remota, que para consultar la tabla “nativa de IRIS” o la tabla basada en el global, pero esta se almacena y actualiza completamente en la nube, y en segundo plano se extrae a IRIS.
Exploremos un par de funciones adicionales de External Table.
## %PATH y las tablas basadas en varios archivos
La carpeta de nuestro ejemplo, que se encuentra en el bucket, contiene solo un archivo. Lo más común es que tenga varios archivos de la misma estructura, donde el nombre del archivo identifique tanto al registro de la hora como al identificador de algún otro atributo que queramos utilizar en nuestras consultas.
El campo %PATH se agrega automáticamente a cada tabla externa y contiene la ruta completa hacia el archivo de donde se recuperó la fila.
select top 5 %PATH,* from covid_by_state
%PATH date state fips cases deaths
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv 2020-01-21 Washington 53 1 0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv 2020-01-22 Washington 53 1 0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv 2020-01-23 Washington 53 1 0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv 2020-01-24 Illinois 17 1 0
s3://covid19-lake/rearc-covid-19-nyt-data-in-usa/csv/us-states/us-states.csv 2020-01-24 Washington 53 1 0
Puede utilizar el campo %PATH en sus consultas SQL como cualquier otro campo.
## De datos ETL a “tablas regulares”
Si su tarea es cargar datos de S3 en una tabla IRIS, puede utilizar External Table como una herramienta ETL. Simplemente haga lo siguiente:
INSERT INTO internal_table SELECT * FROM external_table
En nuestro caso, si queremos copiar los datos COVID de S3 a la tabla local:
--create local table
create table covid_by_state_local (
"date" DATE,
"state" VARCHAR(100),
fips INT,
cases INT,
deaths INT
)
--ETL from External to Local table
INSERT INTO covid_by_state_local SELECT TO_DATE("date",'YYYY-MM-DD'),state,fips,cases,deaths FROM covid_by_state
## UNIÓN entre IRIS, tablas nativas y externas. Consultas federadas
External Table es una tabla SQL. Se puede unir con otras tablas, utilizarse en subconsultas y sistemas de archivos tipo UNION. Incluso puede combinar la tabla “Regular” de IRIS y dos o más tablas externas que provengan de diferentes fuentes en la misma consulta SQL.
Intente crear una tabla regular, por ejemplo, haga coincidir los nombres de los estados con sus códigos como en el caso de Washington y WA. Y únalos con nuestra tabla basada en S3.
create table state_codes (name varchar(100), code char(2))
insert into state_codes values ('Washington','WA')
insert into state_codes values ('Illinois','IL')
select top 10 "date", state, code, cases from covid_by_state join state_codes on state=name
Cambie “join” por “left join” para incluir aquellas filas donde el código del estado no esté definido. Como puede ver, el resultado es una combinación de datos provenientes de S3 y su tabla nativa de IRIS.
## Acceso seguro a la información
El lago de datos Covid en AWS es público. Cualquier persona puede leer los datos que provengan de esta fuente sin la necesidad de tener alguna autenticación o autorización. En la vida real seguramente quiere acceder a sus datos de una forma segura, donde se evite que extraños echen un vistazo a sus archivos. Los detalles completos sobre AWS Identity y Access Management (IAM) están fuera del alcance de este artículo. Pero lo mínimo que debe saber es que necesita por lo menos la clave de acceso a la cuenta y la información confidencial de AWS para acceder a los datos privados de su cuenta.
AWS utiliza la autenticación de claves/información confidencial de la cuenta para firmar las solicitudes. https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html#access-keys-and-secret-access-keys
Si está ejecutando IRIS External Table en una instancia de EC2, la forma recomendada de lidiar con la autenticación es utilizando las funciones que se encuentran en la instancia de EC2 https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html. De este modo, IRIS External Table podría utilizar los permisos de esa función. No se requiere ninguna configuración adicional.
En una instancia local o que no sea de EC2 es necesario especificar AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY, ya sea con la ayuda de variables de entorno o mediante la instalación y configuración del cliente CLI de AWS.
export AWS_ACCESS_KEY_ID=AKIAEXAMPLEKEY
export AWS_SECRET_ACCESS_KEY=111222333abcdefghigklmnopqrst
Asegúrese de que la variable de entorno sea visible dentro del proceso de IRIS. Puede verificarlo al ejecutar:
USER>write $system.Util.GetEnviron("AWS_ACCESS_KEY_ID")
Esto debería emitir el valor de la clave.
O instale el CLI de AWS, mediante instrucciones que se encuentran aquí: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html y ejecutar:
aws configure
Entonces External Table podrá leer las credenciales desde los archivos de configuración para el CLI de AWS. Posiblemente su shell interactivo y el proceso de IRIS estén ejecutándose en cuentas diferentes, asegúrese de ejecutar `aws configure` con la misma cuenta que su proceso de IRIS.
Este artículo ha sido etiquetado como "Mejores prácticas" ("Best practices").
Los artículos con la etiqueta "Mejores prácticas" incluyen recomendaciones sobre cómo desarrollar, probar, implementar y administrar mejor las soluciones de InterSystems.
Artículo
Heloisa Paiva · 1 jun, 2023
Introducción
Entre las diversas soluciones que desarrollamos en Innovatium, un desafío habitual es la necesidad de acceder al tamaño de las bases de datos. Entonces me di cuenta de que eso no es algo tan trivial en IRIS. Ese tipo de información es importante para mantener un control del flujo de datos y del coste en gigabytes de un sistema para implementar. Sin embargo, lo que realmente me llamó la atención fue la necesidad de eso para algo muy importante: la migración a la nube. Al final, ¿quién no quiere migrar sus sistemas a la nube hoy en día?
Los servicios cloud ofrecen, de manera sencilla, todo lo que un sistema necesita: mirroring, escalabilidad, protección de datos, facilidad de flujo y lo que hace que todas las empresas se enamoren: solo se paga por lo que se usa. Y además, con los gigantes Google (Cloud), Microsoft (Azure), Amazon (AWS), etc. ofreciendo sus servicios casi impecables a precios accesibles, es algo que con una pequeña inversión puede ser una realidad para cualquiera que quiera aumentar sus ganancias y ahorrar a largo plazo. Además, para aquellos que ya están aquí, InterSystems también tiene sus propios servicios en la nube.
Por eso os voy a presentar la aplicación que estoy desarrollando, en la cual no solo es posible, sino también es fácil, observar el tamaño de los globals, para que los análisis necesarios para obtener un servicio cloud sean tan complicado como tu proveedor favorito lo complique.
Inspiración
Inspirándome en las aplicaciones isc-global-size-tracing y globals-tool, estoy creando una versión que pueda unir lo mejor de cada una y añadir las adaptaciones necesarias para nuestro negocio. Pero antes de mostrar mi desarrollo, voy a presentar brevemente las aplicaciones comentadas.
isc-global-size-tracing ofrece servicios de análisis a partir de clases dentro de IRIS, con métodos más amigables para el usuario y opciones de tareas programadas que actualizan una tabla con varios datos sobre los globals. Hay también opciones predefinidas para exportar las información a archivos externos. Así, si ya hay conocimiento de ObjectScript no es tan difícil dedicar unos minutos a entender cómo funciona y adaptarlo a tu negocio.
Globals-tool muestra un portal en forma de página web, donde es posible verificar los tamaños asignados y los tamaños disponibles para cada global, dentro de sus namespaces. Es un poco más simple, pero más amigable para el usuario, y también se puede utilizar para compartir los datos con personas de otras áreas sin conocimientos de programación. Los cambios y adaptaciones pueden requerir conocimientos previos no solo de ObjectScript, sino también de React y similares.
Lo que me gustaría entonces es combinar las diversas opciones de la primera con la facilidad de uso de la segunda, además de añadir otras funciones de análisis y exportación.
La aplicación - lo que ya está disponible
En esta sección, voy a explicar un poco lo que ya está hecho y cómo puedes aprovecharlo tú y tu empresa.
Todo el código está disponible para consultar, clonar o descargar en mi Github.
Empezar a utilizarla es muy sencillo, solamente hay que clonar o descargar el repositorio en la carpeta que prefieras y configurar para tu instancia de IRIS.
Abre el terminal en la carpeta donde quieres clonar el repositorio y usa el comando
git clone https://github.com/heloisatambara/iris-size-django
Entra en la carpeta iris-size-django e instala los requisitos necesarios:
.../iris-size-django > pip install -r requirements.txt
Edita el archivo .../iris-size-django/globalsize/settings.py para personalizar la configuración de la base de datos. No cambies el parámetro ENGINE, debe apuntar a la aplicación de CaretDev, django-iris. Sin embargo, hay que cambiar NAME para el namespace, USER y PASSWORD para un usuario con los privilegios adecuados (se requiere acceso al namespace %SYS y poder crear una tabla en el namespace deseado) y los parámetros HOST y PORT deben apuntar a tu instancia.
De vuelta al terminal, vamos a ejecutar los comandos makemigrations para preparar la aplicación, migrate para crear la tabla donde vamos a almacenar la información de los globals y runserver para poner todo en práctica.
> python manage.py makemigrations
> python manage.py migrate
> python manage.py runserver
Ahora, simplemente abre el enlace http://127.0.0.1:8000/globals/ en un navegador y haz clic en Update. En pocos segundos deberías ver una tabla con todos los namespaces y sus respectivos globals, mostrando la cantidad (en megabytes) de memoria asignada y utilizada, como se ve en la imagen al inicio de esta sección.
Ahora vamos a analizar mejor la parte superior de la foto:
Aquí se pueden ver las opciones de filtros, exportación y ordenación.
Puedes escribir parte del nombre de la base de datos o de los globals para ver resultados específicos, o escribir un número positivo en Size o Allocated para ver resultados por encima de ese valor. Si escribes un número negativo, tendrás los resultados debajo del módulo del valor. Haz clic en Filter para aplicar el filtro.
Selecciona el modelo de exportación (CSV, XML, JSON) y haz clic en Export para exportar a la carpeta iris-size-django. Ten en cuenta que los filtros aplicados se reflejarán en la exportación. Además, puedes cambiar la dirección de exportación en el código, en .../iris-size-django/globals/views.py.>
Finalmente, puedes seleccionar el orden ascendente en orden alfabético, por el nombre de la base de datos y del global o por el espacio ocupado o por la cantidad asignada. Haz clic en Filter para efectuar la ordenación y los filtros aplicados. Nota: la ordenación no se reflejará en la exportación.
Al final de la página se puede ver el recuento de globals dentro de los filtros seleccionados, además de la cantidad total asignada y utilizada:
Si quieres hacer análisis más detallados o incluso ver la tabla original, una buena opción es entrar en el portal de administración de la instancia referida en settings.py, en la sesión de SQL y seleccionar el namespace referido en el mismo lugar. La tabla habrá sido creada automáticamente por Django con el nombre de SQL_User.globals_iglobal, y ahí puedes usar las herramientas de InterSystems para ejecutar todo tipo de consultas.
Nota: en settings.py, el parámetro DEBUG está marcado como TRUE, porque aún está en desarrollo.
Ideas futuras
Mis próximas ideas son añadir más funciones al portal. Actualmente es posible modificar configuraciones de exportación y de la base de datos directamente en el código, además de realizar consultas más complejas a través del portal de IRIS. Sin embargo, creo que unificar todo eso en el portal puede ser más eficiente. Además, también estoy estudiando añadir un siguimiento del flujo de datos por período.
Por fin, me gustaría saber vuestra opinión: ¿Creéis que ese tipo de aplicación puede ayudar a vuestros negocio? ¿Qué otras funciones os gustaría ver aquí? ¿Os gustaría ver alguna función ya existente de IRIS de manera más amigable? ¿O preferiríais que algo presentado aquí fuera más simple?