Artículo Nancy Martínez · ene 18, 2023 1m read

En la Comunidad de Desarrolladores hay muchos artículos interesantes que muestran cómo utilizar Jupyter e InterSystems IRIS juntos, y os animo a echarles un vistazo - al final de esta publicación tenéis un enlace a los artículos.

Este es otro de esos artículos. La diferencia con los otros está en la sencillez. ¿Solo quieres iniciar un contenedor en el que Jupyter ya está conectado a una instancia de IRIS? ¡Entonces esto es para ti!

Solo con ejecutar docker-compose up ya podrás acceder a un entorno de trabajo con un par de ejemplos.

No quiero estropear la sencillez, así que probadlo.

login

Más artículos sobre IRIS y Jupyter:

0
0 119
Artículo Nancy Martínez · nov 14, 2022 2m read

¡Amigos!

Hace poco encontré en la Comunidad varios comandos de ObjectScript de una única línea y creo que estaría genial no perderlos y recopilar más.

Por eso he decidido recoger unos cuantos ejemplos, ponerlos en este proyecto en Open Exchange, y compartirlos con vosotros!

Así es como podéis usarlos.

1. Crear la configuración SSL del cliente

set $namespace="%SYS", name="DefaultSSL" do:'##class(Security.SSLConfigs).Exists(name) ##class(Security.SSLConfigs).Create(name)

Útil si necesitáis leer contenido de una URL.

0
0 142
Artículo Nancy Martínez · oct 18, 2022 1m read

¡Hola desarrolladores!

Para mí, una de las peores cosas de ObjectScript es tener que escribir la sentencia ##class(Class).Method() para llamar a un método de clase en código o en un terminal. Incluso envié una idea para simplificarlo en ObjectScript.

¡Pero! Hay una nueva funcionalidad en VSCode ObjectScript que acaba de ser añadida al plugin - ¡Copy Invocation!

Solo hay que poner el cursor sobre el enlace Copy Invocation que aparece encima de cada método de clase del código, hacer clic en él y la invocación se copia en el buffer:

Pegadlo donde queráis que se ejecute.

0
0 161
Artículo Nancy Martínez · sep 8, 2022 2m read

¡Hola desarrolladores!

Los que usáis Dockerfile para trabajar con InterSystems IRIS a menudo tenéis que  ejecutar varias líneas de ObjectScript. Para mí, esto era el juego de "escapar de esto y aquello" cada vez, solo para ejecutar unos pocos comandos en ObjectScript a IRIS. Idealmente, preferiría programar en ObjectScript sin usar comillas o caracteres de escape.

Recientemente he encontrado un buen "hack" sobre cómo esto podría ser mejorado a exactamente este estado. Lo cogí del repositorio de @Dmitry Maslennikov y te permite usar Objectscript de una forma como si lo escribieras en el terminal de IRIS.

Esto es lo que tienes en dockerfile:

///
COPY irissession.sh /
SHELL ["/irissession.sh"]
RUN \
  do $SYSTEM.OBJ.Load("Installer.cls", "ck") \
  set sc = ##class(App.Installer).setup()
# bringing the standard shell back
SHELL ["/bin/bash", "-c"]
CMD [ "-l", "/usr/irissys/mgr/messages.log" ]
///
0
0 100
Artículo Nancy Martínez · ago 19, 2022 1m read

¡Hola desarrolladores!

Me gustaría compartir con vosotros un truco útil para presentar código de ObjectScript en ficheros Script en VSCode.

Los ficheros Script son simplemente ficheros con líneas de ObjectScript que introducimos en cualquier sitio, por ejemplo en IRIS durante el procedimiento Docker baking.

Caso de uso típico - este es el Scriptfile

este es el Dockerfile donde lo introducimos.

Y así es como se ve normalmente en VSCode:

Screenshot 2021-08-05 at 09 51 06

Podría ser más elegante, ¿verdad?

0
0 139
Artículo Nancy Martínez · ago 2, 2022 1m read

¡Hola desarrolladores!

Solo quiero compartir una antigua pero muy relevante buena práctica en el cambio de namespaces que @Dmitry Maslennikov compartió conmigo.

Consideremos el método:

classmethod DoSomethingInSYS() as %Status

{

set sc=$$$OK

set ns=$namespace

zn "%SYS"

// try-catch in case there will be an error

try {

// do something, e.g. config change

}

catch {}

 zn ns    ; returning back to the namespace we came in the routine

return sc

}
0
0 172
Artículo Nancy Martínez · jul 22, 2022 1m read

¡Hola desarrolladores!

Solo quiero compartir con vosotros mi conocimiento, es decir, experiencia en algo que os puede hacer ahorrar unas cuantas horas algún día. 

Si estás creando una REST API con IRIS que contiene más de un nivel de "/", por ejemplo: '/patients/all',  no te olvides de añadir el parámetro 'recurse=1' en tu script de despliegue en %Installer. Si no, todas las entradas de nivel secundario y de mayor profundidad no funcionarán. Y todas las entradas de nivel primario funcionarán.

/patients

- funcionará, pero

/patients/all

- no funcionará.  

Este es un ejemplo de sección CSPApplication que arregla el problema y que puede que quieras usar en tu clase %Installer:

    <CSPApplication Url="${CSPAPP}"
      Recurse="1"
      Directory="${CSPAPPDIR}"
      Grant="${RESOURCE},%SQL"
      AuthenticationMethods="96"
      />
0
0 156
Artículo Nancy Martínez · mayo 30, 2022 1m read

Estoy seguro de que os habéis encontrado esta situación:

  • Hay un bug en un sistema que no puedes reproducir por ti mismo localmente
  • Necesitas ejecutar unas pocas líneas en la instancia afectada
  • Tienes acceso completo al Portal de Gestión
  • Pero no hay terminal, ni consola, ni acceso con Studio, Atelier o VSCode
  • ¿Cómo ejecutar tus pocas líneas para probar???
1
0 203
Artículo Nancy Martínez · feb 23, 2022 5m read

Os voy a contar cómo hacer una migración de Ensemble a IRIS para chuparse los dedos, es una receta antigua que me pasó mi abuela pero yo le he puesto algunos detallitos. Aquí os la dejo para que cuando os toque alguna podáis tenerlo paso a paso.

Preparar los Nuevos servidores

Lo primero de todo es instalar y configurar la nueva instancia de IRIS, aqui prestamos especial atención a dimensionar adecuadamente el servidor. Atención a la memoria y al espacio en disco para el sistema, para los journals, para las bases de datos y también para los backups. Tambien tened en cuenta si vais a acceder desde puestos remotos en habilitar los puertos adecuados de los firewalls, normalmente usaremos el 22 si hacemos SSH, el 1972 si usamos el Studio y el puerto 52773 para acceder al portal. Aunque si no os gustan esos puertos podeis poner otros. Ya sabeis que la cocina hay que mantenerla siempre limpia y ordenada!

Instalamos IRIS

Pues nada, instalamos IRIS y luego configuramos Global buffers y Routine buffers. Ya sabeis que eso es más importante y casi lo único a configurar para que la cocción salga en su punto. Otra cosa a tocar es la configuración de journals, para evitar que el principal y el alternativo sean el mismo directorio. Así IRIS se queda más tranquilo y nos evitamos algunos warnings que luego salpica todo y aqui que usar el quitagrasas!. Alguna cosilla más que tocar, eliminar la opción de desactivar cuenta después de 90 días de inactividad, porque a veces se queda mucho tiempo sin acceder y te encuentras que no hay manera de entrar. Y a ver quien abre el horno a 200º !!

Tomar nota de todo

En la cocina hay que apuntar todos los ingredientes y ahora toca hacer el catalogo de Namespaces y producciones del servidor que vamos a migrar, anotamos que producciones están en marcha y cuales no y le echamos un vistazo a cada una. No está de más algún pantallazo de algunos detalles para recordar y tomar notas. Que luego la foto del making-of queda muy chula!

Exportar, exportar

Exportamos las producciones y todas las clases que sean de usuario dentro de un Namespace. Eso lo podemos hacer desde el Studio o incluso desde el portal. Al final la idea es tener un paquete XML con todas las clases necesarias de cada Namespace que despues dejaremos en remojo al menos una noche.

Replicar, replicar

Mientras tenemos las clases en remojo, en el nuevo servidor creamos las bases de datos y atenderemos al recurso que se usa, al directorio donde se crea y al nombre de cada una. Espolvorear con sal marina y un poco de aceite.

Ya es el turno de la creación de los Namespaces, esto es fácil, le ponemos un nombre le asociamos las bases de datos creadas y que no se nos olvide que el check para habilitar la interoperabilidad del namespace esté activado para que podamos importar las producciones sin problema. Lo metemos todo en una olla de tamaño grande. Más cositas, ¿qué tal unas aplicaciones Web? pican un poco pero a veces hay aplicaciones web adicionales, tenedlo en cuenta al revisar las producciones del servidor original.

Esto va a gusto del consumidor. Otros ingredientes que debemos tener en cuenta son:

SQL Gateways

Esto es algo muy común en producciones que acceden a bases de datos externas y usan JDBC. Para ello lo primero a tener en cuenta es que en IRIS la versión mínima soportada de JAVA es la 1.8. Podemos usar OpenJDK, por ejemplo para un sistema Linux RedHat podemos instalar OpenJDK11 con un solo comando:

sudo yum install java-11-openjdk-devel

Y tambien es importante obtener los driver JDBC necesarios y colocarlos en una carpeta adecuada. No olvideis descongelarlos con tiempo.

Ahora nos toca exportar todos los SQL Gateways del servidor original. Esto se puede hacer exportando la tabla %Library.sys_SQLConnection como un fichero de texto tipo CSV desde el portal. Es recomendable usar un carácter separador de campos fácilmente reconocible como el |. Y tomad nota de las columnas porque entre versiones el número de columnas o campos de la clase puede cambiar. Normalmente si hay campos nuevos no son obligatorios o necesarios.

Configuraciones SSL

Otros ingredientes comunes son las configuraciones SSL, sobre todo si se usan comunicaciones seguras mediante HTTPS para servicios REST o SOAP. Para ello lo primero copiar los certificados existentes del servidor original y moverlos al nuevo servidor si es posible en las mismas carpetas, sino recordad que luego tendremos que tocarlos a mano.

Para exportar desde el antiguo servidor usaremos:

%SYS>w ##class(Security.SSLConfigs).Export("YYMMDD_SSLConfigsExport.xml")

Y para importar en el nuevo:

%SYS>w ##class(Security.SSLConfigs).Import("YYMMDD_SSLConfigsExport.xml",.NumImported)

Podemos comprobar cuantos se han importado con la variable que hemos pasado por referencia NumImported.

Credenciales

Estas son un rollo, se pueden hacer al ajillo o salteadas pero no he encontrado como exportarlas y se deben hacer a mano. Así que nos toca preguntar las passwords de cada una de ellas. Si encontrais como automatizar esta tarea ponedlo en los comentarios ;-)

Default Settings

Otro ingrediente que aparece por ahi. Hay que revisar y tenerlos en cuenta porque son útiles y si no lo movemos tendremos un problema. Podemos exportalos mediante:

MYNAMESPACE>w ##class(Ens.Config.DefaultSettings).%Export("YYMMDD_MYNAMESPACE_DefaultSettings.xml")

Ojo que esto debeis hacerlo por cada namespace!!. Podeis Importarlos mediante:

MYNAMESPACE>w ##class(Ens.Config.DefaultSettings).%Import("YYMMDD_MYNAMESPACE_DefaultSettings.xml",.NumImported)

Igualmente con NumImported podemos comprobar cuantos settings se han importado.

Importar las clases y compilar

Esto es fácil, vamos por cada namespace importando el fichero XML que exportamos y cruzamos los dedos para que todo vaya bien. De vez en cuando algo no compila bien y toca corregir algún detalle, lo probamos con una cucharita pequeña y con cuidado de no quemarnos. Luego es útil hacer un $system.OBJ.CompileAll() para que así se compile todas las clases dependientes o las que se quedaron sin compilar. Y quedan deliciosas!

Una vez que tenemos esto lo ideal es probar las producciones de manera individual, pero solo un poco que hay que dejar algo para los comensales. Comprobad que todo funciona como debiera siempre con entornos de prueba y no con la vajilla nueva. Esto es lo más pesado y además tendremos que molestar a más gente para validar que la integración hace lo mismo que antes.

Y para terminar postre

Por ejemplo reproducir busquedas guardadas de mensajes si es que había y sobre todo reproducir las tareas programadas que existiesen en el servidor original. Podemos reducirlas con Pedro Ximenez y quedan bien dulces. Reproducir la configuración de Backups, borrado de journals y purgados de mensajerías. Y si seguis usando el Studio, que para mi gusto repite un montón, no olvidar actualizar instalaciones de las máquinas de desarrollo para que puedan acceder a la nueva instancia.

Pues nada, ya teneis una migración rica rica y con fundamento!!

0
0 190
Artículo Nancy Martínez · abr 20, 2021 2m read

Al trabajar desde casa durante estos "días de coronavirus", me faltan recursos.

  • no tengo ninguna máquina Linux disponible
  • espacio en disco limitado

Además, Docker Desktop (en Windows10) bloqueó de alguna manera los scripts de Durable %SYS como se describe aquí.
Investigando el caso, descubrí que se almacenaban muchos más datos de los que realmente necesitaba.
Así que diseñé mi durabilidad personalizada.

De forma similar a lo que hice tiempo atrás para los contenedores de Caché.

Utilizando las características de **iris-main **agrego un script de pre-procesamiento para iniciar mi contenedor con 

Después de que termina, guardo lo que creo necesitar para el próximo inicio.

Y eso es bastante menos.
De acuerdo: Puede que se me escapen algunas cosas y finalmente es más lento en start/stop. Muy bien. ¡Pero está en mis manos!
  Los scripts para ejecutar y también los datos guardados están almacenados en el directorio externo que necesito para la licencia.
Y esos scripts son bastante sencillos:

# post.copy
cp -uf /usr/irissys/iris.cpf /external/iris.cpf
cp -uf /usr/irissys/mgr/IRIS.DAT /external/mgr/IRIS.DAT
cp -uf /usr/irissys/mgr/messages.log /external/console.log

y

# pre.copy
cp -f /external/iris.cpf /usr/irissys/iris.cpf
cp -f /external/mgr/IRIS.DAT /usr/irissys/mgr/IRIS.DAT
rm -f /usr/irissys/mgr/messages.log

Como no hay nada que configurar en la primera ejecución, omito pre.copy como la primera ejecución hecha.
Por lo demás, mi comando de ejecución en Docker tiene el siguiente aspecto:

docker run --name iris1 --init -it 
 -p 52773:52773 -p 51773:51773 
 --volume c:/external:/external 
 --rm 
intersystems/iris:2020.2.0.198.0 
  --key /external/key/iris.key 
  -e /external/post.copy 
  -b /external/pre.copy 

Si tiempo después descubro que necesito guardar/recuperar algo más (por ejemplo, para CSP, ... ) es fácil añadirlo.
La clave del éxito fue dejar la base de datos IRISSYS en la ubicación que se incluye en el contenedor. Su tamaño de ~92 MB (en mi caso) no es relevante.

0
0 115
Artículo Nancy Martínez · mar 31, 2021 2m read

Este es el ejemplo de un código para visualizar JSON o un objeto dinámico.

Muestra cómo iterar sobre object, get property values y sus rutas.

Class JSON.Test
{

/// do ##class(JSON.Test).Test()
ClassMethod Test()
{
    set json = "{""a"":1,""b"":2,""c"":{""c1"":3,""c2"":4}, ""d"": [5, {""e_e"":6}, 7]}"

    set obj = {}.%FromJSON(json)

    do ..Iterate(obj)
}

ClassMethod Iterate(obj As %DynamicAbstractObject, level = 0, path = "obj")
{
    set indent = $j("", level * 4)
    #dim iterator As %Iterator.Array
    set iterator = obj.%GetIterator()

    while iterator.%GetNext(.key, .value) {
        set type = obj.%GetTypeOf(key)
        write indent, "Key: ", key, !
        write indent, "Type: ", type, !

        if $classname(obj) = "%Library.DynamicArray" {
            set newPath = path _ ".%GetAt(" _ key _ ")"
        } else {
            if $zname(key, 6) = 1 {
                set newPath = path _  "." _ key
            } else {
                set newPath = path _  ".""" _ key _ """"
            }
        }

        write indent, "Path: ", newPath, !
        if $isObject(value) {
            write indent, "Value: ", !
            do ..Iterate(value, level + 1, newPath)
        } else {
            write indent, "Value: ", value, !
        }
        write !
    }
}

}

Esta es la salida después de ejecutar el método de prueba (Test method):

Key: a
Type: number
Path: obj.a
Value: 1

Key: b
Type: number
Path: obj.b
Value: 2

Key: c
Type: object
Path: obj.c
Value:
    Key: c1
    Type: number
    Path: obj.c.c1
    Value: 3

    Key: c2
    Type: number
    Path: obj.c.c2
    Value: 4


Key: d
Type: array
Path: obj.d
Value:
    Key: 0
    Type: number
    Path: obj.d.%GetAt(0)
    Value: 5

    Key: 1
    Type: object
    Path: obj.d.%GetAt(1)
    Value:
        Key: e_e
        Type: number
        Path: obj.d.%GetAt(1)."e_e"
        Value: 6


    Key: 2
    Type: number
    Path: obj.d.%GetAt(2)
    Value: 7
1
0 401
Artículo Nancy Martínez · feb 2, 2021 3m read

¿Qué es OData?

OData (Open Data Protocol) es un estándar OASIS, con certificación ISO/IEC, que define un conjunto de prácticas recomendadas para construir y consumir APIs RESTful. OData te ayuda a enfocarte en tu lógica de negocio mientras construyes APIs RESTful, sin tener que preocuparte por los diversos enfoques para definir cabeceras de solicitud y respuesta, códigos de estado, métodos HTTP, convenciones URL, tipos de medios audiovisuales, formatos de carga, opciones de consulta, etc. OData también proporciona orientación para registrar cambios, definir funciones/acciones para llevar a cabo procedimientos reutilizables y enviar solicitudes asíncronas/por lotes (Fuente: OData.org).

0
0 194
Artículo Nancy Martínez · dic 10, 2020 5m read

Los sistemas de bases de datos tienen requisitos muy específicos para las copias de seguridad ("backups") que, en entornos empresariales, necesitan una previsión y planificación. En el caso de los sistemas de bases de datos, el objetivo de una copia de seguridad es crear una copia de los datos en un estado equivalente a cuando la aplicación se apaga de forma correcta. Las copias de seguridad consistentes con las aplicaciones cumplen estos requisitos, y Caché ofrece un conjunto de APIs que facilitan la integración con soluciones externas para lograr este nivel de consistencia en las copias de seguridad.

0
0 144
Artículo Nancy Martínez · sep 25, 2020 4m read

Método: para descargar el archivo FTP desde Caché de InterSystems: Si tienes cualquier consulta, deja un mensaje por favor:

ClassMethod FTPDownload(myFTP = "", myUserName = "", myPassword = "", sFileLocation = "", dLocation = "", noOfdownloadFile = 1, sourceFileDel = 0)
{
 /*---------------------------------------------------------------------------------------------------------------------------
descargar el archivo según los requirimientos: FTP

Método: Resuable 

creado por: Sanjib Raj Pandey el 30/03/2018

0
0 246
Artículo Nancy Martínez · jul 22, 2020 8m read

Ejemplos de Mapeos

Obviamente, si tienes un cuatro artículo en la trilogía, debes apostar por las ganancias económicas y escribir el quinto, ¡así que aquí está!

Nota: Hace muchos años, Dan Shusman me dijo que el mapeo de globals es una forma de arte. No existe una manera correcta o incorrecta de hacerlo. El modo en que interpretes los datos te llevará al tipo de mapeo que realizas. Como siempre, existe más de una forma de llegar a la respuesta final. Según vayas revisando mis ejemplos, verás que hay algunos en los que se mapean el mismo tipo de datos, pero de distintas maneras.

0
0 190
Artículo Nancy Martínez · jul 3, 2020 5m read

El objetivo de esta "Guía para solucionar problemas en DeepSee" es ayudar a localizar y solucionar los problemas en un proyecto en DeepSee.

Si el problema no puede solucionarse siguiendo estas recomendaciones, al menos tendrás suficiente información para reportar el problema al Centro de Soporte Internacional (WRC) y proporcionarnos todas la información, para que podamos continuar la investigación juntos y resolverlo más rápido!

1
0 218
Artículo Nancy Martínez · abr 16, 2020 10m read


A partir de la versión 2019.2, InterSystems IRIS ofrece su API nativa para Python como un método de alto rendimiento para acceso a datos. La API nativa permite interactuar directamente con la estructura de datos nativa de IRIS.

Globals

Como desarrolladores de InterSystems, seguramente ya estais familiarizados con los globals. Vamos a revisar los aspectos básicos por si os apetece un repaso, pero podéis saltar a la siguiente sección si no lo necesitáis.

0
0 273
Artículo Nancy Martínez · mar 13, 2020 9m read

Introducción

Un requisito frecuente en muchas aplicaciones es registrar en una base de datos los cambios que se realizan en los datos- qué datos se modificaron, quién los modificó y cuándo (control de cambios). Hay muchos artículos relacionados con el tema y existen diferentes métodos sobre cómo hacer esto en Caché.

1
0 399
Artículo Nancy Martínez · ene 20, 2020 5m read

¡Hola Comunidad!

HealthShare utiliza muchas transformaciones XSL. Estas transformaciones se utilizan para convertir los documentos médicos de la iniciativa “Integración de las Empresas Sanitarias (IHE)” en SDA (formatos interno de HealthShare), y convertirlos nuevamente en los formatos IHE, con el fin de crear resúmenes de los informes y para lidiar con los perfiles en el IHE (por ejemplo, consultar la información de los pacientes, proporcionar documentos y registrarlos). Los clientes pueden configurar las XSLT para personalizar los informes, o para utilizarlas de alguna otra manera.

Para la depuración y el desarrollo es muy conveniente que se pueda ejecutar un XSLT desde el Terminal.

0
0 226
Artículo Nancy Martínez · dic 18, 2019 3m read

Pregunta:

¿Cómo obtengo un listado de los archivos que se encuentran dentro de cierta carpeta/directorio, usando un comodín/filtro?

Por ejemplo, todos los archivos '*.txt' en 'C:\Temp.

Respuesta:

En CACHE:

Puedes usar la consulta de clase FileSet de %Library.File.

Aquí puedes ver el ejemplo de un código donde se usa (también se adjunta):

0
0 255
Artículo Nancy Martínez · nov 21, 2019 5m read

¡Hola Comunidad!

Como explicó Rob en un artículo anterior, la interfaz Node.js de Caché permite crear Servicios Web y Servicios REST utilizando el  framework modular framework EWD 3.

Por defecto, estos servicios devuelven una respuesta JSON con Content-Type: application / json y el cuerpo de respuesta contiene el JSON que devuelve utilizando el método finished(), por lo que:

finished({ test: 'test response' });

devuelve

{ "test": "test response" }

con un content-type HTTP de application/json

0
0 1636
Artículo Nancy Martínez · nov 14, 2019 4m read

¡Hola a tod@s!

Buscando en la Comunidad propuestas para trabajar con datos organizados en hojas EXCEL, de forma sencilla, para ofrecer a los usuarios finales, encontré este buen artículo sobre el tema: Tips & Tricks - SQL to Excel, que introduce un concepto importante: "EXCEL puede interpretar tablas HTML y mostrarlas de la forma habitual"
¡Genial!

0
0 206
Artículo Nancy Martínez · oct 8, 2019 7m read

Las herramientas que utilizan los astrónomos

Hace 6 años, el 19 de diciembre del 2013, la Agencia Espacial Europea (ESA) lanzó un telescopio orbital llamado Gaia. Podéis obtener más información sobre la misión Gaia en la página web oficial de la Agencia Espacial Europea o en el artículo de Vitaly Egorov (Billion pixels for a billion stars).

Y sin embargo, pocas personas saben cuál fue la tecnología que utilizó la agencia para almacenar y procesar los datos recopilados por Gaia. En 2011, dos años antes del lanzamiento, los desarrolladores barajaban varias opciones (consultar "Astrostatistics and Data Mining" escrito por Luis Manuel Sarro, Laurent Eyer, William O'Mullane, Joris De Ridder, pp. 111-112):

0
0 173
Artículo Nancy Martínez · sep 30, 2019 2m read

¡Hola a tod@s!

Cuando se ejecuta la tarea integrada de Purga en Ensemble (Ens.Util.Tasks.Purge) existen tres parámetros: DaysToKeep, BodiesToo y KeepIntegrity. Este artículo se centra en el parámetro de tipo booleano KeepIntegrity, pero podéis encontrar más información sobre cómo ejecutar esta tarea en el siguiente link:

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

KeepIntegrity determina qué mensajes de Ensemble se marcan para ser borrados dentro del tiempo especificado en el parámetro DaysToKeep.

0
0 146