#Caché

0 Seguidores · 369 Publicaciones

  

InterSystems Caché es un multi-modelo de DBMS y la aplicación server. See más detalles aquí.

Documentación.

Descargar Evaluación de Caché.

Pregunta Yone Moreno · abr 18, 2023

Buenos días;

Primeramente, expresar gracias reales sinceras y profundas por el tiempo que dedican ustedes a leer, entender y responder esta duda. Sobre todo muchas gracias por responderla de la mejor manera posible. Gracias.

Tenemos una duda:

El Sistema Origen nos informa en el body que envía hacia el método del Servicio REST "getCursosAdmitidosInscripcionAbierta" de la siguiente manera:

{
    "agrupacionPuesto": ["37","38"]
}

 

Siendo el Mensaje Request:

1
0 289
Pregunta Yone Moreno · abr 17, 2023

Buenos días;

Primero agradecer infinito el apoyo de ustedes y sobre todo y más importante el tiempo que dedican a leer, comprender y sobre todo a responder esta duda. Muchísimas gracias.

Hemos estado trasteando en un Servicio REST para adaptarlo a tal y como lo necesita Sistema Origen. Observamos que si nos enviaran una Header con mayúsculas "idUserLogueado" al tratar de obtener valor en Servicio en el LOGINFO sale vacío:

set idUserLogueado = pInput.GetAttribute("idUserLogueado")

$$$LOGINFO("idUserLogueado: "_idUserLogueado)
2
0 268
Anuncio Esther Sanchez · abr 12, 2023

¿Habéis oído hablar del Design Thinking? ¿O habéis oído hablar de ello y pensado: "Yo no soy diseñador, ¿cuándo usaría yo el Design Thinking?" Si bien un diseñador dedicado es responsable de aplicar las prácticas de Design Thinking en una organización, cualquier persona que cree productos puede beneficiarse de una mentalidad Design Thinking. Según Forbes, las prácticas de Design Thinking pueden "proporcionar un ROI del 85% o más". También puede reducir los ciclos de desarrollo de productos en un 33-50%.

person writing on white paper

0
0 104
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
InterSystems Official David Reche · mar 27, 2023

InterSystems anuncia la Versión de Mantenimiento (Maintenance Release, MR) 2018.1.8 de Caché, Ensemble y HSAP. Es una versión de mantenimiento con muchas actualizaciones en una gran variedad de áreas.

Caché y Ensemble

Los kits completos de instalación de producto se pueden descargar de la página de distribución de software del Centro de Soporte Internacional (WRC):

0
0 131
InterSystems Official Jose-Tomas Salvador · mar 27, 2023

InterSystems está comprometida con ofrecer un soporte de alta calidad de todos sus productos, nuevos y antiguos. A medida que los productos envejecen – Caché tiene ahora 25 años – ese soporte va evolucionando.

InterSystems IRIS fue lanzado en 2018 y es el sucesor de Caché y Ensemble. Muchos clientes de Caché/Ensemble han migrado a IRIS o tienen planes de hacerlo en los próximos años. Los clientes que siguen usando Caché o Ensemble deben tener en cuenta este anuncio importante:

0
0 122
Artículo Daniel Aguilar · mar 18, 2023 4m read

Una de las razones por las que me encantan Cache e IRIS es que no solo puedes hacer cualquier cosa que puedas imaginar, sino que también puedes hacerlas de un montón de maneras diferentes!!

Imagina que tienes una integración con IRIS (o Cache) funcionando conectada por ODBC. Probablemente solo uses consultas SQL, pero puedes usar también procedimientos almacenados y dentro de su código puedes hacer cualquier cosa que puedas imaginar.

Voy a darte algunos ejemplos, pero el límite está en tu imaginación!

Quizás te estés diciendo... ¡espera!! Yo no sé como crear un procedimiento almacenado en IRIS... Pero eso no es cierto, sabes crearlo! Lo que pasa que todavía no lo sabes...

0
0 267
Pregunta Yone Moreno · mar 13, 2023

Buenos días;

Antes que nada agradecer el tiempo, conocimiento y dedicación de ustedes, al leer y responder esta cuestión.

Actualmente disponemos de un circuito que recibe SOAP y envía SOAP, relacionado con la Administración Electrónica; el cual hemos generado al importar el WSDL del Sistema Destino.

Lo interesante y el desafío es lo siguiente:

Si por SoapUI cargamos el WSDL de Sistema Destino y enviamos 1 mensaje SOAP directos, nos responden OK

Sin embargo, curiosamente, al enviar el mismo mismo mismo mensaje, por el ESB, nos da una Excepción el Sistema Destino:

3
0 364
Artículo Daniel Aguilar · feb 13, 2023 6m read

Hola! recientemente tuve que aplicar validación api-key a un desarrollo que teníamos hecho con un montón de endpoints y me he decidido a compartir con vosotros como lo llevé a cabo de una forma centralizada.

En este artículo os voy a explicar como podemos aplicar de una forma genérica (o no) validación api key a todos los endpoints de nuestra Web App.

Para el desarrollo utilicé la clase Base.cls de la plantilla iris-rest-api-template

5
0 593
InterSystems Official Jose-Tomas Salvador · mar 3, 2023

InterSystems actualiza periódicamente sus políticas y prácticas de lanzamiento de nuevas versiones software para ajustarse a las necesidades de los clientes.

Ahora estamos cambiando la frecuencia de nuestras versiones de mantenimiento para que sean más predecibles para clientes y partners, y modificaremos algunas otras áreas.
En este artículo se resume la frecuencia de lanzamientos de nuestras Plataformas de datos y los cambios recientes en ellas, y se anuncian algunas actualizaciones nuevas.

0
0 90
Artículo Ricardo Paiva · feb 24, 2023 11m read

En el primer artículo hablé sobre probar y depurar aplicaciones web de Caché con herramientas externas. La segunda parte tratará sobre las herramientas de Caché.

Estas son:

  • CSP Gateway y Webapp configuration
  • CSP Gateway logging
  • CSP Gateway tracing
  • ISCLOG
  • Custom logging
  • Session events
  • Output to device

CSP Gateway y Webapp configuration

En primer lugar, si estás depurando y, sobre todo, desarrollando una aplicación front-end, no necesitas caching. Es muy útil en un sistema de producción, pero no durante el desarrollo. Para desactivar el registro de una aplicación web, hay que ir a: SMP → Menu → Manage Web Applications → <Your Web App> y definir Serve Files Timeout con la configuración igual a 0. Luego hacer clic en "Save".

Después, hay que purgar el caché de la aplicación web. Para ello, ve a: SMP → System Administration → Configuration → CSP Gateway Management → System Status. Allí se encuentra la tabla "Cached Forms", la última fila es una línea Total, pulsa el botón borrar (con el punto) para borrar el caché de la aplicación web:

CSP Gateway logging

Ya que estamos hablando de CSP Gateway, este es compatible con el registro de las solicitudes de entrada (documentación). En la pestaña Default Parameters, especifica el nivel de registro deseado (por ejemplo, v9a) y guarda los cambios. v9a (consulta otras opciones en la documentación) registra todas las solicitudes HTTP a http.log en el directorio principal de Gateway. Este es un ejemplo de solicitud capturada:

GET /forms/form/info/Form.Test.Person HTTP/1.1
Host: localhost:57772
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:57772/formsui/index.html
Cookie: CSPSESSIONID-SP-57772-UP-forms-=001000000000yxiocLLb8bbc9SVXQJC5WMU831n2sENf4OGeGa; CSPWSERVERID=144zwBTP
Dnt: 1
Connection: keep-alive
Cache-Control: max-age=0
&lt;>

También hay opciones para registrar el rendimiento. Los resultados pueden escribirse en un archivo o visualizarse desde la pestaña View Event Log.

CSP Gateway tracing

Por último, se pueden rastrean las solicitudes y respuestas en la pestaña View HTTP Trace de CSP Gateway. Activa el rastreo y las solicitudes comenzarán a ser capturadas inmediatamente. No olvides apagarlo después de realizar la depuración. Este es un ejemplo de sesión de depuración:

Nota: utiliza el rastreo si puedes identificar cuál es el problema y reproducirlo fácilmente. Utiliza el registro para recoger estadísticas, elaborar perfiles de rendimiento, etc.

Además, la mayoría de los servidores web ofrecen herramientas de registro y seguimiento del rendimiento.

ISCLOG

CSP Gateway es útil para determinar problemas de red y hacer seguimiento del rendimiento, pero para registrar lo que ocurre dentro de Caché se necesitan otras herramientas. Una de las herramientas más versátiles es ISCLOG. Documentación.

Es un global que puede almacenar información sobre el procesamiento de las solicitudes actuales. Para iniciar el registro, ejecuta:

set ^%ISCLOG = 2

Y para terminar el registro, ejecuta:

set ^%ISCLOG = 0

Este es el ejemplo de una solicitud:

^%ISCLOG=0
^%ISCLOG("Data")=24
^%ISCLOG("Data",1)=$lb(2,"CSPServer","Header from CSP Size:3744 CMD:h IdSource:3","4664","FORMS","2017-06-07 10:49:21.341","%SYS.cspServer2","","")
^%ISCLOG("Data",1,0)="^h30000 "_$c(14,0,0)_"A"
^%ISCLOG("Data",2)=$lb(2,"CSPServer","[UpdateURL] Looking up: //localhost/forms/form/info path found: //localhost/forms/ Appl= "_$c(2,1,3,4)_"@"_$c(3,4,1,2,1,9,1)_"/forms/"_$c(2,1,3,4,1,2,1,2,1,2,4,3,4,1,2,1,9,1,7,1)_":%All"_$c(8,1)_"/forms"_$c(7,1)_"FORMS"_$c(2,1,2,1,3,4,1,2,1,2,1,3,4,1,2,1,4,4,132,3,3,4,2,3,4,2,2,1,4,4,16,14,2,4,3,4,1,3,4,1,2,1,3,4,1,2,1,16,1)_"Form.REST.Main"_$c(2,4,2,4),"4664","FORMS","2017-06-07 10:49:21.342","%CSP.Request.1","124","L3DfNILTaE")
^%ISCLOG("Data",3)=$lb(2,"CSPServer","[UpdateURL] Found cls: Form.REST.Main nocharsetconvert:  charset:UTF-8 convert charset:UTF8","4664","FORMS","2017-06-07 10:49:21.342","%CSP.Request.1","124","L3DfNILTaE")
^%ISCLOG("Data",4)=$lb(2,"CSPServer","[HTML] Determined request type","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer2","124","L3DfNILTaE")
^%ISCLOG("Data",4,0)=$lb("usesession",1,"i%Class","Form.REST.Main","i%Service","REST","NOLOCKITEM","","i%GatewayError","")
^%ISCLOG("Data",5)=$lb(2,"CSPSession","[%LoadData] Loading CSP session, nosave=0","4664","FORMS","2017-06-07 10:49:21.342","%CSP.Session.1","","L3DfNILTaE")
^%ISCLOG("Data",5,0)=$lb(900,,0,5567742244,$c(149)_"Ù"_$c(3)_"ó»à"_$c(127)_",½"_$c(149,10)_"\"_$c(18)_"v"_$c(128,135)_"3Vô"_$c(11)_"*"_$c(154)_"PÏG¥"_$c(140,157,145,10,131)_"*",2,"FORMS","001000000000L3DfNILTaE1cDBJNjyQdyLwKq4wCXP82ld8gic",,0,"ru","L3DfNILTaE",2,1,"/forms/",$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737),"","","","2017-06-07 10:48:51","2017-06-07 10:49:04","Basic ZGV2OjEyMw==","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0","","",0,"/forms/","","","",4,"","","","","http://localhost:57772/formsui/index.html")
^%ISCLOG("Data",6)=$lb(2,"CSPServer","[CSPDispatch]Requested GET /forms/form/info","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",7)=$lb(2,"CSPServer","[CSPDispatch] ** Start processing request newSes=0","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",7,0)="/forms/form/info"
^%ISCLOG("Data",8)=$lb(2,"CSPServer","[CSPDispatch] Service type is REST has-soapaction=0 nosave=0","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",9)=$lb(2,"CSPServer","[CSPDispatch]About to run page: Form.REST.Main","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",9,0)=$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737)
^%ISCLOG("Data",10)=$lb(2,"CSPServer","[callPage] url=/forms/form/info ; Appl: /forms/ newsession=0","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",11)=$lb(2,"CSPServer","[callPage]Imported security context ; User: UnknownUser ; Roles: %All,%Developer","4664","FORMS","2017-06-07 10:49:21.342","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",12)=$lb(2,"CSPServer","[OutputCSPGatewayData]: chd=1;","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Response.1","","L3DfNILTaE")
^%ISCLOG("Data",13)=$lb(2,"CSPResponse","[WriteHTTPHeaderCookies] Session cookie: CSPSESSIONID-SP-57772-UP-forms-=001000000000L3DfNILTaE1cDBJNjyQdyLwKq4wCXP82ld8gic; path=/forms/;  httpOnly;","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Response.1","124","L3DfNILTaE")
^%ISCLOG("Data",14)=$lb(2,"CSPServer","[callPage] Return Status","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",14,0)=1
^%ISCLOG("Data",15)=$lb(2,"CSPServer","[OutputCSPGatewayData]: chd=1;","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Response.1","","L3DfNILTaE")
^%ISCLOG("Data",16)=$lb(2,"CSPServer","[Cleanup]Page EndSession=0; needToGetALicense=-1; nosave=0; loginredirect=0; sessionContext=1","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",17)=$lb(2,"CSPSession","[Cleanup] EndSession=0 nosave=0","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","124","L3DfNILTaE")
^%ISCLOG("Data",18)=$lb(2,"CSPSession","[%SaveData] Saved: ","4664","FORMS","2017-06-07 10:49:21.431","%CSP.Session.1","","L3DfNILTaE")
^%ISCLOG("Data",18,0)=$lb(900,,0,5567742261,$c(149)_"Ù"_$c(3)_"ó»à"_$c(127)_",½"_$c(149,10)_"\"_$c(18)_"v"_$c(128,135)_"3Vô"_$c(11)_"*"_$c(154)_"PÏG¥"_$c(140,157,145,10,131)_"*",2,"FORMS","001000000000L3DfNILTaE1cDBJNjyQdyLwKq4wCXP82ld8gic",,0,"ru","L3DfNILTaE",2,1,"/forms/",$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737),"","","","2017-06-07 10:48:51","2017-06-07 10:49:21","Basic ZGV2OjEyMw==","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0","","",0,"/forms/","","","",5,"","","","","http://localhost:57772/formsui/index.html")
^%ISCLOG("Data",19)=$lb(2,"CSPServer","[Cleanup] Restoring roles before running destructor","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","","L3DfNILTaE")
^%ISCLOG("Data",19,0)=$lb("UnknownUser","%All,%Developer","%All,%Developer",64,-559038737)
^%ISCLOG("Data",20)=$lb(2,"CSPServer","[Cleanup] End","4664","FORMS","2017-06-07 10:49:21.431","%SYS.cspServer","","L3DfNILTaE")
^%ISCLOG("Data",20,0)="&lt;-Finish processing request->"
^%ISCLOG("Data",21)=$lb(2,"GatewayRequest","[CSPGWClientRequest] GWID: ed-pc:57772; Request: sys_get_system_metricsTimeout: 5","11112","%SYS","2017-06-07 10:49:23.141","%SYS.cspServer3","","")
^%ISCLOG("Data",22)=$lb(2,"GatewayRequest","[CSPGWClientRequest] GWID: 127.0.0.1:57772; Request: sys_get_system_metricsTimeout: 5","11112","%SYS","2017-06-07 10:49:23.141","%SYS.cspServer3","","")
^%ISCLOG("Data",23)=$lb(2,"GatewayRequest","[SendSimpleCmd:Server:Failed] WebServer: 127.0.0.1:57772; Gateway Server Request Failed","11112","%SYS","2017-06-07 10:49:23.141","%CSP.Mgr.GatewayMgrImpl.1","","")
^%ISCLOG("Data",23,0)=0
^%ISCLOG("Data",24)=$lb(2,"GatewayRequest","[GetMetrics]","11112","%SYS","2017-06-07 10:49:23.141","%CSP.Mgr.GatewayMgrImpl.1","","")
^%ISCLOG("Data",24,0)="&lt;-End Request Client->"

Además, este es un script rápido para la salida de global a un archivo:

set p="c:\temp\isclog.txt"
open p:"NW"
use p zw ^%ISCLOG
close p

 

Custom logging

Aunque las herramientas de registro predeterminadas son bastante buenas, tienen varios problemas:

  • Son genéricas y no están familiarizadas con tu solicitud
  • Las opciones más detalladas afectan al rendimiento
  • No están bien estructuradas, por lo que puede resultar difícil extraer información

Por lo tanto, se pueden cubrir casos más específicos escribiendo sistemas de registro personalizados. Este es un ejemplo de una clase persistente que registra parte del objeto %request:

/// Incoming request
Class Log.Request Extends %Persistent
{
/// A string indicating HTTP method used for this request.
Property method As %String;
/// A string containing the URL up to and including the page name
/// and extension, but not including the query string.
Property url As %String(MAXLEN = "");
/// A string indicating the type of browser from which the request
/// originated, as determined from the HTTP_USER_AGENT header.
Property userAgent As %String(MAXLEN = "");
/// A string indicating the MIME Content-Type of the request.
Property contentType As %String(MAXLEN = "");
/// Character set this request was send in, if not specified in the HTTP headers
/// it defaults to the character set of the page it is being submitted to.
Property charSet As %String(MAXLEN = "");
/// A &lt;class>%CSP.Stream&lt;/class> containing the content submitted
/// with this request.
Property content As %Stream.GlobalBinary;
/// True if the communication between the browser and the web server was using
/// the secure https protocol. False for a normal http connection.
Property secure As %Boolean;
Property cgiEnvs As array Of %String(MAXLEN = "", SQLPROJECTION = "table/column");
Property data As array Of %String(MAXLEN = "", SQLPROJECTION = "table/column");
ClassMethod add() As %Status
{
    set request = ..%New()
    quit request.%Save()
}
Method %OnNew() As %Status [ Private, ServerOnly = 1 ]
{
    #dim %request As %CSP.Request
    #dim sc As %Status = $$$OK
    quit:'$isObject($g(%request)) $$$ERROR($$$GeneralError, "Not a web context")
    set ..charSet = %request.CharSet
    if $isObject(%request.Content) {
        do ..content.CopyFromAndSave(%request.Content)
    } else {
        set ..content = ""
    }
    set ..contentType = %request.ContentType
    set ..method = %request.Method
    set ..secure = %request.Secure
    set ..url = %request.URL
    set ..userAgent = %request.UserAgent
    set cgi = ""
    for {
        set cgi=$order(%request.CgiEnvs(cgi))
        quit:cgi=""
        do ..cgiEnvs.SetAt(%request.CgiEnvs(cgi), cgi)
    }
    // Only gets first data if more than one data with the same name is present
    set data = ""
    for {
        set data=$order(%request.Data(data))
        quit:data=""
        do ..data.SetAt(%request.Get(data), data)
    }
    quit sc
}
}

Para añadir un nuevo registro a la tabla Log.Request, agrega una llamada a tu código:

do ##class(Log.Request).add()

Es un ejemplo muy básico, puede y debe ampliarse para registrar comentarios, variables o cualquier otra cosa que puedas necesitar. La principal ventaja de este enfoque es la posibilidad de ejecutar consultas SQL sobre los datos registrados.  Para obtener más información sobre cómo crear tu propio sistema de registro, consulta este artículo.

Session events

La clase Event (Evento) es una clase que define las interfaces que se llaman durante la vida de un objeto %CSP.Session. Para utilizarla, hay que subclasificar %CSP.SessionEvents e implementar el código del método que quieres ejecutar. A continuación, en la configuración de la aplicación CSP, hay que establecer la clase de evento en la clase que has creado.

Las siguientes devoluciones de llamada están disponibles:

  • OnApplicationChange
  • OnEndRequest
  • OnEndSession
  • OnLogin
  • OnLogout
  • OnStartRequest
  • OnStartSession
    • OnTimeout

    Por ejemplo, los custom loggings comentado anteriormente pueden invocarse desde estos métodos.

    Output to device

    Una de las opciones más sencillas - un método de utilidad CSP que muestra todos los objetos como respuesta. Solo hay que añadir esto a cualquier parte de tu código:

    set %response.ContentType = "html"
    do ##class(%CSP.Utils).DisplayAllObjects()
    return $$$OK

     

    Conclusión

    Hay varias herramientas que se puede utilizar para depurar las aplicaciones web. Elige la más adecuada para la tarea que vayas a realizar.

      Y vosotros... ¿tenéis algún consejo o truco para depurar aplicaciones web desde Caché?

    0
    0 141
    Artículo Muhammad Waseem · oct 13, 2021 4m read

    A lo largo de los años, me he encontrado con la necesidad de crear varios mensajes HL7 basados en un solo mensaje entrante. Por lo general, toman la forma de un pedido o son el resultado de un laboratorio. Cada vez que he afrontado el reto, he intentado empezar de cero, con la convicción de que el intento anterior podría haberse hecho mejor.

    Recientemente, volvió a surgir la necesidad y pude crear una solución de la que no me avergonzaba. Mi principal preocupación era que siempre me encontraría enterrado en un BPL, o usaría ObjectScript e intentaría editar mensajes usando el método SetValueAt para la clase de mensaje HL7.

    Problema
    Cuando el Sistema A procesa múltiples pedidos para un solo paciente, el resultado vendrá en un solo mensaje con ORCgrp repetido con los segmentos OBR y OBX contenidos en este. El sistema B solo puede recibir un único OBR por mensaje.

    1
    1 388
    InterSystems Official Mario Sanchez Macias · feb 21, 2023

    15 de febrero de 2023

    InterSystems ha corregido un problema que puede hacer que InterSystems IRIS® y Caché no aprovechen las páginas grandes (large pages) para memoria compartida en Windows, aunque estos productos informen de que las páginas grandes están asignadas. Esto puede afectar al rendimiento del sistema.

    El problema proviene de un cambio en Windows 10 que requiere una modificación de InterSystems IRIS® y Caché. Hay que tener en cuenta que este problema también afecta a todos los productos de InterSystems que están basados en InterSystems IRIS® o Caché. El problema ocurre en las siguientes versiones de Windows:

    0
    0 130
    Artículo Kurro Lopez · jun 16, 2020 9m read

    En mi anterior artículo, revisamos los posibles casos de uso para macros, así que pasemos ahora a un ejemplo más completo de usabilidad de macros. En este artículo diseñaremos y crearemos un sistema de registro.

    Sistema de registro

    El sistema de registro es una herramienta útil para monitorear el trabajo de una aplicación que ahorra mucho tiempo durante la depuración y el monitoreo. Nuestro sistema constaría de dos partes:

    • Clase de almacenamiento (para registros de anotaciones)
    • Conjunto de macros que agregan automáticamente un nuevo registro al registro

    Clase de almacenamiento

    Vamos a crear una tabla de lo que necesitamos almacenar y especificar cuándo se pueden obtener estos datos, durante la compilación o en tiempo de ejecución. Esto será necesario cuando trabaje en la segunda parte del sistema: macros, donde buscaremos tener tantos detalles registrables como sea posible durante la compilación:

    InformaciónObtenido durante
    Tipo de eventoCompilación
    Nombre de claseCompilación
    Nombre del métodoCompilación
    Argumentos pasados ​​a un métodoCompilación
    Número de línea en el código fuente de clsRuntime
    Número de línea en el código int generadoRuntime
    Nombre de usuarioRuntime
    Date/TimeRuntime
    MensajeRuntime
    direccion IPRuntime

    Vamos a crear una clase App.Log que contenga las propiedades de la tabla anterior. Cuando se crea un objeto App.Log, las propiedades de UserName, TimeStamp y ClientIPAddress se completan automáticamente.

    App.Log class:

    Class App.Log Extends %Persistent
    {
    

    /// Type of event Property EventType As %String(MAXLEN = 10, VALUELIST = ",NONE,FATAL,ERROR,WARN,INFO,STAT,DEBUG,RAW") [ InitialExpression = "INFO" ];

    /// Name of class, where event happened Property ClassName As %String(MAXLEN = 256);

    /// Name of method, where event happened Property MethodName As %String(MAXLEN = 128);

    /// Line of int code Property Source As %String(MAXLEN = 2000);

    /// Line of cls code Property SourceCLS As %String(MAXLEN = 2000);

    /// Cache user Property UserName As %String(MAXLEN = 128) [ InitialExpression = {$username} ];

    /// Arguments' values passed to method Property Arguments As %String(MAXLEN = 32000, TRUNCATE = 1);

    /// Date and time Property TimeStamp As %TimeStamp [ InitialExpression = {$zdt($h, 3, 1)} ];

    /// User message Property Message As %String(MAXLEN = 32000, TRUNCATE = 1);

    /// User IP address Property ClientIPAddress As %String(MAXLEN = 32) [ InitialExpression = {..GetClientAddress()} ];

    /// Determine user IP address ClassMethod GetClientAddress() { // %CSP.Session source is preferable #dim %request As %CSP.Request If ($d(%request)) { Return %request.CgiEnvs("REMOTE_ADDR") } Return $system.Process.ClientIPAddress() } }

     

    Macros de registro

    Por lo general, las macros se almacenan en archivos * .inc separados que contienen sus definiciones. Los archivos necesarios se pueden incluir en clases usando el comando Include MacroFileName, que en este caso se verá de la siguiente manera: Include App.LogMacro.
     
    Para comenzar, definamos la macro principal que el usuario agregará al código de su aplicación:

    #define LogEvent(%type, %message) Do ##class(App.Log).AddRecord($$$CurrentClass, $$$CurrentMethod, $$$StackPlace, %type, $$$MethodArguments, %message)

    Esta macro acepta dos argumentos de entrada: Tipo de evento y Mensaje. El usuario define el argumento Mensaje, pero el parámetro Tipo de evento requerirá macros adicionales con diferentes nombres que identificarán automáticamente el tipo de evento:

    #define LogNone(%message)         $$$LogEvent("NONE", %message)
    #define LogError(%message)        $$$LogEvent("ERROR", %message)
    #define LogFatal(%message)        $$$LogEvent("FATAL", %message)
    #define LogWarn(%message)         $$$LogEvent("WARN", %message)
    #define LogInfo(%message)         $$$LogEvent("INFO", %message)
    #define LogStat(%message)         $$$LogEvent("STAT", %message)
    #define LogDebug(%message)        $$$LogEvent("DEBUG", %message)
    #define LogRaw(%message)          $$$LogEvent("RAW", %message)

    Por lo tanto, para realizar el registro, el usuario solo necesita colocar la macro $$$LogError("Additional message") en el código de la aplicación.
    Todo lo que necesitamos hacer ahora es definir las macros $$$CurrentClass, $$$CurrentMethod, $$$StackPlace, $$$MethodArguments.Comencemos con las tres primeras:

    #define CurrentClass     ##Expression($$$quote(%classname))
    #define CurrentMethod    ##Expression($$$quote(%methodname))
    #define StackPlace       $st($st(-1),"PLACE")

    %classname, %methodname las variables se describen en la documentacion. La función $stack devuelve el número de línea del código INT. Para convertirlo en un número de línea CLS, podemos usar este código.

    Usemos el paquete %Dictionary para obtener una lista de argumentos de métodos y sus valores. Contiene toda la información sobre las clases, incluidas las descripciones de los métodos. Estamos particularmente interesados ​​en la clase %Dictionary.CompiledMethod y su propiedad FormalSpecParsed, que es una lista:

    $lb($lb("Name","Classs","Type(Output/ByRef)","Default value "),...)

    correspondiente a la firma del método. Por ejemplo:

    ClassMethod Test(a As %Integer = 1, ByRef b = 2, Output c)

    tendrá el siguiente valor FormalSpecParsed:

    $lb(
    $lb("a","%Library.Integer","","1"),
    $lb("b","%Library.String","&","2"),
    $lb("c","%Library.String","*",""))

    Necesitamos que la macro $$$MethodArguments se expanda en el siguiente código (para el método Test):

    "a="_$g(a,"Null")_"; b="_$g(b,"Null")_"; c="_$g(c,"Null")_";"

    Para lograr esto, tenemos que hacer lo siguiente durante la compilación:

    1. Obtenga un nombre de clase y un nombre de método
    2. Abra una instancia correspondiente de la clase %Dictionary.CompiledMethod y obtenga su propiedad FormalSpec
    3. Conviértalo en una línea de código fuente

    Agreguemos los métodos correspondientes a la clase App.Log:

    ClassMethod GetMethodArguments(ClassName As %String, MethodName As %String) As %String
    {
        Set list = ..GetMethodArgumentsList(ClassName,MethodName)
        Set string = ..ArgumentsListToString(list)
        Return string
    }
    

    ClassMethod GetMethodArgumentsList(ClassName As %String, MethodName As %String) As %List { Set result = "" Set def = ##class(%Dictionary.CompiledMethod).%OpenId(ClassName _ "||" _ MethodName) If ($IsObject(def)) { Set result = def.FormalSpecParsed } Return result }

    ClassMethod ArgumentsListToString(List As %List) As %String { Set result = "" For i=1:1:$ll(List) { Set result = result _ $$$quote($s(i>1=0:"",1:"; ") _ $lg($lg(List,i))"=") _ "$g(" _ $lg($lg(List,i)) _ ","$$$quote(..#Null)")_" _$s(i=$ll(List)=0:"",1:$$$quote(";")) } Return result }


    Ahora definamos la macro $$$MethodArguments como:

    #define MethodArguments ##Expression(##class(App.Log).GetMethodArguments(%classname,%methodname))

    Caso de uso

    A continuación, creemos una clase App.Use con un método de prueba para demostrar las capacidades del sistema de registro:

    Include App.LogMacro
    Class App.Use [ CompileAfter = App.Log ]
    {
    /// Do ##class(App.Use).Test()
    ClassMethod Test(a As %Integer = 1, ByRef b = 2)
    {
        $$$LogWarn("Text")
    }
    }

    Como resultado, la macro $$$LogWarn("Text") en el código int se convierte en la siguiente línea:

    Do ##class(App.Log).AddRecord("App.Use","Test",$st($st(-1),"PLACE"),"WARN","a="_$g(a,"Null")_"; b="_$g(b,"Null")_";", "Text")

    La ejecución de este código creará un nuevo registro de App.Log:

    Mejoras

    Después de haber creado un sistema de registro, aquí hay algunas ideas de mejora:

    • En primer lugar, existe la posibilidad de procesar argumentos de tipo objeto ya que nuestra implementación actual solo registra objetos oref.
    • Segundo, una llamada para restaurar el contexto de un método a partir de valores de argumentos almacenados.

    Procesamiento de argumentos de tipo objeto

    La línea que pone un valor de argumento en el registro se genera en el método ArgumentsListToString y tiene este aspecto:

    "_$g(" _ $lg($lg(List,i)) _ ","_$$$quote(..#Null)_")_"

    Realicemos una refactorización y muévala a un método GetArgumentValue separado que acepte un nombre y clase de variable (todo lo que sabemos de FormalSpecParsed) y genere un código que convertirá la variable en una línea. Usaremos el código existente para los tipos de datos, y los objetos se convertirán en JSON con la ayuda de los métodos SerializeObject (para llamar desde el código de usuario) y WriteJSONFromObject (para convertir un objeto en JSON):

    ClassMethod GetArgumentValue(Name As %String, ClassName As %Dictionary.CacheClassname) As %String
    {
        If $ClassMethod(ClassName, "%Extends", "%RegisteredObject") {
            // it's an object
            Return "_##class(App.Log).SerializeObject("_Name _ ")_"
        } Else {
            // it's a datatype
            Return "_$g(" _ Name _ ","_$$$quote(..#Null)_")_"
        }
    }
    

    ClassMethod SerializeObject(Object) As %String { Return:'$IsObject(Object) Object Return ..WriteJSONFromObject(Object) }

    ClassMethod WriteJSONFromObject(Object) As %String [ ProcedureBlock = 0 ] { Set OldIORedirected = ##class(%Device).ReDirectIO() Set OldMnemonic = ##class(%Device).GetMnemonicRoutine() Set OldIO = $io Try { Set Str=""

        //Redirect IO to the current routine - makes use of the labels defined below
        Use $io::("^"_$ZNAME)
    
        //Enable redirection
        Do ##class(%Device).ReDirectIO(1)
    
        Do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(Object)
    } Catch Ex {
        Set Str = ""
    }
    
    //Return to original redirection/mnemonic routine settings
    If (OldMnemonic '= "") {
        Use OldIO::("^"_OldMnemonic)
    } Else {
        Use OldIO
    }
    Do ##class(%Device).ReDirectIO(OldIORedirected)
    
    Quit Str
    
    // Labels that allow for IO redirection
    // Read Character - we don't care about reading
    

    rchr(c) Quit // Read a string - we don't care about reading rstr(sz,to) Quit // Write a character - call the output label wchr(s) Do output($char(s)) Quit // Write a form feed - call the output label wff() Do output($char(12)) Quit // Write a newline - call the output label wnl() Do output($char(13,10)) Quit // Write a string - call the output label wstr(s) Do output(s) Quit // Write a tab - call the output label wtab(s) Do output($char(9)) Quit // Output label - this is where you would handle what you actually want to do. // in our case, we want to write to Str output(s) Set Str = Str_s Quit }

    Una entrada de registro con un argumento de tipo objeto se ve así:

    Restaurando el contexto

    La idea de este método es hacer que todos los argumentos estén disponibles en el contexto actual (principalmente en la terminal, para la depuración). Para este fin, podemos usar el parámetro del método ProcedureBlock. Cuando se establece en 0, todas las variables declaradas dentro de dicho método permanecerán disponibles al salir del método. Nuestro método abrirá un objeto de la clase App.Log y deserializará la propiedad Argumentos.

    ClassMethod LoadContext(Id) As %Status [ ProcedureBlock = 0 ]
    {
        Return:'..%ExistsId(Id) $$$OK
        Set Obj = ..%OpenId(Id)
        Set Arguments = Obj.Arguments
        Set List = ..GetMethodArgumentsList(Obj.ClassName,Obj.MethodName)
        For i=1:1:$Length(Arguments,";")-1 {
            Set Argument = $Piece(Arguments,";",i)
            Set @$lg($lg(List,i)) = ..DeserializeObject($Piece(Argument,"=",2),$lg($lg(List,i),2))
        }
        Kill Obj,Arguments,Argument,i,Id,List
    }
    

    ClassMethod DeserializeObject(String, ClassName) As %String { If $ClassMethod(ClassName, "%Extends", "%RegisteredObject") { // it's an object Set st = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(String,,.obj) Return:$$$ISOK(st) obj } Return String }

    Así es como se ve en la terminal:

    >zw
    >do ##class(App.Log).LoadContext(2)
    >zw
    

    a=1 b=<OBJECT REFERENCE>[2@%ZEN.proxyObject]

    >zw b b=<OBJECT REFERENCE>[2@%ZEN.proxyObject] +----------------- general information --------------- | oref value: 2 | class name: %ZEN.proxyObject | reference count: 2 +----------------- attribute values ------------------ | %changed = 1 | %data("prop1") = 123 | %data("prop2") = "abc" | %index = ""

    ¿Que sigue?

    La mejora potencial clave es agregar otro argumento a la clase de registro con una lista arbitraria de variables creadas dentro del método.

    Conclusiones

    Las macros pueden ser bastante útiles para el desarrollo de aplicaciones.

    Preguntas

    ¿Hay alguna manera de obtener el número de línea durante la compilación?

    Links

    1
    0 242
    Anuncio Alberto Fuentes · feb 16, 2023

    Para todos aquellos que aún utilizáis el IDE Studio para programar con ObjectScript y vais a pasar por el proceso de migración a VS Code, ¿sabíais que hay una sección en la documentación de VS Code justo para vosotros? Echad un vistazo al apartado Migración desde Studio. Incluye los siguientes aspectos:

    • Edición del lado del servidor y control de código fuente
    • Proyectos de Studio
    • Importación de definiciones de servidor desde el Registro de Windows
    • Carga de fragmentos de código de Studio y colores de sintaxis

    Y ahora hay una sección llamada Atajos de teclado, que muestra los atajos equivalentes en VS Code a los que estéis acostumbrados, para que las manos no tengan que dejar el teclado. En muchos casos el atajo es el mismo, por lo que no será necesario re-aprender. Y recordad, todos los atajos en VS Code son configurables por el usuario, por lo que tendréis un nivel de control que Studio nunca ofreció.

    0
    0 122
    Pregunta Yone Moreno · feb 9, 2023

    Buenas tardes,
    Por favor agradeceríamos que nos lean y respondan.

    Necesitamos dada una solicitud de Autenticación emitida hacia nuestro servidor de autorización OAuth 2.0; que en caso de error, el mensaje respondido sea personalizado.

    Actualmente si apuntamos desde POSTMAN a:
    https://[IP]:[Puerto]/oauth2/token?grant_type=client_credentials&scope=my/scope

    Username: Erróneo
    Password: Errónea

    Obtenemos:
    {
        "error": "server_error",
        "error_description": "ERROR #5002: Error de cache: <INVALID OREF>zAuthorize+28^OAuth2.Server.Token.1"
    }

    1
    0 147
    Artículo Daniel Aguilar · feb 5, 2023 2m read

    Hola Comunidad!

    Quiero compartir con vosotros mi primera aplicación del Open Exchange.

    Es una herramienta para hacernos los desarrollos mas fáciles. Es un microservicio con IRIS en un docker que nos ayuda en los desarrollos de campañas de SMS, Mail y en los links para las tiendas de nuestras apps brindándonos un acortador de Url's.

    Es muy fácil de usar.

    Simplemente clona este repo:

    https://github.com/daniel-aguilar-garcia/cos-url-shortener.git

    Abre la carpeta en VSCode y arranca el docker:

     

    2
    0 223
    Pregunta Paco Cadenas · dic 14, 2022

    Hola!

    Entiendo no hay automatismo para actualizar código antiguo que imbrica con "puntitos" transformándolo a código con llaves "{ }", creo que hacer un parser de este tipo sería complejo por situaciones como esta :

    Alguien sabe si este código es equivalente ?

    VERSION CON PUNTITOS
     Use fic

    Read *R:20 Else  Do  Quit    ;;;;  comando else aplicado a read.
      . Use 0 Write !!!,"Temps expirat."
     If $c(R)="a" d
      . Use 0 Write !!!,"Ha leido una letra a"
      . Quit
     
    VERSION CON LLAVES
     Use fic
     Read *R:20
     If $Test {
    Use 0 Write !!!,"Ha leido un carácter"
    Quit
     }
     Else {
    Use 0 Write !!!,"Temps expirat."
     }
     

    3
    0 133
    Pregunta Federico Mazzei · ene 9, 2023

    Hola chicos, soy nuevo en este foro y también con la base de datos InterSystems CACHE. 
    Comento que tengo la Base de Datos en una PC que estaba funcionando sin ningún problema hasta que empezó a arrojarme este error que muestro a continuación:
     

    Eh intentado varias formas de levantarlo pero no logro hacerla funcionar.
    Busqué el archivo cconsole.log dentro de todos los directorios de mi PC y no se ha encontrado nada. También he mirado los eventos de Windows y lo que encontré fue esto.
     

    - <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">

    - <System>

    3
    0 318
    Artículo Alberto Fuentes · dic 19, 2022 2m read

    Todos los desarrolladores hemos cometido alguna vez el error de accidentalmente dejar código temporal de depuración en lugar de eliminarlo al finalizar lo que estamos investigando.

    Lo interesante de escribir en ObjectScript es que hay una forma de hacer que el código provisional sea realmente provisional y se auto-destruya automáticamente! Incluso puede hacerse de manera que el código no aparezca en tu sistema de control de código fuente, lo que puede ser útil igualmente.

    El secreto radica en utilizar el "intermediate code" (.INT), que se genera cuando se compilan clases (.CLS), código de rutina (.MAC) o páginas CSP (.CSP).  El código INT se utiliza entonces para crear el código OBJ, que es el que finalmente se ejecuta.

    1
    0 136
    Artículo Luis Angel Pérez Ramos · dic 14, 2022 2m read

    En este artículo, mostraré cómo subir y descargar archivos vía http desde los productos de InterSystems.

    A menudo desde la comunidad surgen preguntas sobre como trabajar con archivos a través de http y normalmente os emplazamos a revisar el proyecto FileServer, que muestra la subida/descarga de archivos. Pero me gustaría hablar un poco más de cómo podemos enviar y recibir archivos desde los productos de InterSystems.

    Cómo descargar un archivo

    Si tenéis un archivo en un sistema de archivos y conocéis su ruta, podéis enviarlo vía REST o en el contexto de CSP llamando a este método:

    1
    0 992
    Artículo Alberto Fuentes · dic 14, 2022 1m read

    Las rutinas con privilegios te permiten elevar los roles de un usuario mientras las utiliza. Estas rutinas con privilegios (Privileged Routine Application) pueden utilizarse con rutinas y también con clases / métodos.

    Cuando las utilices, es importante asegurarse de incluir new $ROLES, antes de elevar los privilegios con AddRoles(). Por ejemplo:

    new$ROLESset status=$System.Security.AddRoles("MyPrivilegedRoutineApplication")
    0
    0 142
    Artículo Alberto Fuentes · nov 15, 2022 4m read

    YASPE es el sucesor de YAPE (Yet Another pButtons Extractor). YASPE ha sido escrito desde cero con muchos cambios internos para facilitar el mantenimiento y añadir mejoras.

    Funcionalidades de YASPE:

    • Analizar y representar gráficamente los archivos de InterSystems Caché pButtons e InterSystems IRIS SystemPerformance para un rápido análisis de rendimiento de las métricas de IRIS y del Sistema Operativo.
    • Facilitar un análisis profundo, creando gráficos tanto ad-hoc como combinando métricas de IRIS y del Sistema Operativo con la opción "Pretty Performance".
    • La opción "System Overview" te ahorra tener que buscar en los archivos SystemPerformance detalles del sistema u opciones de configuración comunes.

    YASPE está escrito en Python y está disponible en GitHub como código fuente o para contenedores Docker en:


    YASPE está más centrado en las versiones y Sistema Operativo actuales de IRIS. Si tienes versiones más antiguas y tienes problemas con YASPE, comprueba si puedes ejecutar correctamente tus archivos de rendimiento con YAPE. Si tienes problemas, no dudes en preguntarme a través de GitHub.


    Ejemplos

    Archivos de salida

    Las opciones incluyen:

    • Gráficos en HTML o PNG para todas las columnas en mgstat y vmstat o windows perfmon y salida a carpetas.
    • Es opcional crear gráficos para iostat ya que puede llevar mucho tiempo si hay una lista de discos grande.
    • Un fichero CSV para posterior procesado manual, por ejemplo, con Excel.

    Sample Chart

    Pretty Performance

    Debajo está el gráfico de ejemplo, Glorefs (mgstat) y Uso Total de CPU (vmstat).

    image example1

    Esta es una de las imágenes predeterminadas, que incluye un zoom para un momento específico (o por defecto de 13:00-14:00).

    image example2

    Descripción del sistema

    yaspe incluye una descripción del sistema y una comprobación básica de la configuración (-s)

    Esta comprobación está diseñada para evitar estar rebuscando en el archivo SystemPerformance para encontrar los detalles del sistema. Este es un ejemplo deoverview.txt:

    System Summary for your site name
    
    Hostname         : YOURHOST
    Instance         : SHADOW
    Operating system : Linux
    Platform         : N/A
    CPUs             : 24
    Processor model  : Intel(R) Xeon(R) Gold 6248 CPU @ 2.50GHz
    Memory           : 126 GB
    Shared memory    : globals 71680 MB + routines 1023 MB + gmheap 1000 MB = 73,703 MB
    Version          : Cache for UNIX (Red Hat Enterprise Linux for x86-64) 2018.1.4 (Build 505_1U) Thu May 28 2020 10:11:16 EDT
    Date collected   : Profile run "24hours" started at 16:15:00 on Nov 22 2021.
    
    Warnings:
    - Journal freeze on error is not enabled. If journal IO errors occur database activity that occurs during this period cannot be restored.
    - swappiness is 10. For databases 5 is recommended to adjust how aggressive the Linux kernel swaps memory pages to disk.
    - Hugepages not set. For performance, memory efficiency and to protect the shared memory from paging out, use huge page memory space. It is not advisable to specify HugePages much higher than the shared memory amount because the unused memory are not be available to other components.
    - dirty_background_ratio is 10. InterSystems recommends setting this parameter to 5. This setting is the maximum percentage of active memory that can be filled with dirty pages before pdflush begins to write them.
    - dirty_ratio is 30. InterSystems recommends setting this parameter to 10. This setting is the maximum percentage of total memory that can be filled with dirty pages before processes are forced to write dirty buffers themselves during their time slice instead of being allowed to do more writes. These changes force the Linux pdflush daemon to write out dirty pages more often rather than queue large amounts of updates that can potentially flood the storage with a large burst of updates
    
    Recommendations:
    - Review and fix warnings above
    - Set HugePages, see IRIS documentation: https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=GCI_prepare_install#GCI_memory_big_linux
    - Total memory is 128,755 MB, 75% of total memory is 96,566 MB.
    - Shared memory (globals+routines+gmheap) is 73,703 MB. (57% of total memory).
    - Number of HugePages for 2048 KB page size for (73,703 MB + 5% buffer = 77,388 MB) is 38694
    
    All instances on this host:
    - >SHADOW            2018.1.4.505.1.a  56772  /cachesys
    

    0
    0 89
    InterSystems Official Jose-Tomas Salvador · nov 11, 2022

    Me alegra anunciar un nuevo hito en el ciclo de vida de ObjectScript Package Manager (ZPM). El gestor de paquetes ha ofrecido a los desarrolladores la posibilidad de empaquetar de forma clara y sencilla el código de ObjectScript y la configuración de sus parámetros de despliegue, así como la información de la versión. Durante los últimos años ha evolucionado mucho, convirtiéndose en una parte fundamental de muchos workflows de desarrollo.

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

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

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

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

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

    1
    0 524
    Anuncio Luis Angel Pérez Ramos · oct 21, 2022

    Quiero anunciar el lanzamiento de algo muy interesante - y revolucionario, de hecho. Puede sonar exagerado, pero no creo que hayáis visto nada como esto, ¡ni si quiera imaginar que sería posible!

    Hemos sacado un nuevo módulo JavaScript/Node.js llamado glsdb del que podéis leer todo aquí:

    https://github.com/robtweed/glsdb

    No obstante, para el propósito de este anuncio, me voy a centrar en una parte de glsdb: sus APIs que abstraen las Clases de IRIS (o Cache) como Objetos JavaScript equivalentes.

    Con esto quiero decir que los Objetos de JavaScript serán en realidad ¡Objetos IRIS persistidos en la base de datos! 

    0
    0 99
    Artículo Daniel Aguilar · oct 10, 2022 3m read

    Hola desarrolladores!,

    Ya se lo que estáis pensando. " Una mejora para ZEN.proxyObject...??? ¿Ahora...????

    Bueno en España tenemos el dicho de mas vale tarde que nunca.  ;-)

    ¿Alguna vez has necesitado enviar un atributo numérico de un JSON en formato String?

    ¿Te volviste loco casteando objetos de clases con propiedades fijas y tipadas?

    Pues estás de enhorabuena!! porque ahora podrás hacerlo fácilmente!!.

    1
    0 121