Nouvelle publication

Rechercher

Annonce
· Fév 26

[Video] Unit Testing with IPM

Hey Community,

Enjoy the new video on InterSystems Developers YouTube:

⏯ Unit Testing with IPM

This is a demo of how to add unit tests to an IRIS application using the InterSystems Package Manager. Covered are how to create new unit tests, the Package Manager commands to run tests, and how to track code coverage statistics using the ObjectScript TestCoverage package.

🗣  Presenter: @Pravin Barton, Principal Applications Developer, InterSystems

Enjoy watching, and look for more videos! 👍

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer
Article
· Fév 26 7m de lecture

La puissance de Python intégré dans l'interopérabilité - un cas d'utilisation de MongoDB CDC

L'utilisation de Embedded Python lors de la création d'une solution basée sur InterSystems peut ajouter des fonctionnalités très puissantes et approfondies à votre boîte à outils.

J'aimerais partager un exemple de cas d'utilisation que j'ai rencontré : l'activation d'un CDC (Change Data Capture) pour une collection mongoDB - la capture de ces modifications, leur digestion via un flux d'interopérabilité et, pour finir, la mise à jour d'un EMR via une API REST.

La fonctionnalité principale – « Observation des changements » 👀

L'idée de base est d'utiliser le package PyMongo, qui, entre autres, permet de suivre les modifications au sein d'une base de données mongo via son change_streams.

La partie importante se trouve dans l'adaptateur entrant que j'ai créé et qui possède une méthode OnInit() qui inclut cette ligne :

self.changeStream = client.get_database(...).get_collection(...).watch()

J'utilise la méthode watch() ici pour surveiller les changements d'une collection spécifique dans une base de données.

Je les ai définis via les paramètres du service métier :

Ensuite, dans la méthode OnTask(), j'utilise ceci pour capturer les modifications :

while self.changeStream.alive:
    change = self.changeStream.try_next()
    if change is not None:

Ici, j'utilise la propriété alive et la méthode try_next() pour obtenir les détails des modifications survenues.

Pour chaque modification, je crée un objet IRIS Stream avec le contenu JSON et je l'envoie à la méthode ProcessInput() du service métier.

Dans le service métier, je crée une requête importée à partir du contenu JSON et je l'envoie au routeur.

Le flux général peut être illustré comme suit :

Voici une démonstration vidéo :

Quelques détails techniques supplémentaires 👩‍💻

Le service métier doit « masser » un peu le JSON car il inclut du JSON « flou », avant que je puisse autoriser son importation en tant que JSON valide.

Par exemple, un message peut ressemble à ceci:

 
Exemple de message JSON de capture de changement 

Vous pouvez voir par exemple que Timestamp et new UUID ne sont pas des JSON valides.

Vous pouvez voir que le « Document » actuel se trouve dans la partie fullDocument, et pour cet exemple j'ai utilisé un schéma spécifique.

Mon document ressemble à ceci :

 
Exemple de document JSON pour cette démo

Dans votre cas, vous pouvez soit modifier cela pour l'adapter à votre schéma, soit même envisager d'adapter mon exemple pour utiliser une approche plus « dynamique » où vous pouvez définir un paramètre qui serait utilisé pour importer dynamiquement le JSON vers un nom de classe variable (par rapport à mon nom codé en dur).

[Dans tous les cas, pour charger votre schéma JSON et créer une classe à partir de celui-ci, vous pouvez utiliser la classe Sample.OpenAPIClassGenerator que j'ai incluse dans mon exemple (adapté du générateur de classe de définition OpenAPI de @Guillaume Rongier (et appeler la méthode ProcessFile() que j'ai ajoutée sur votre fichier de schéma JSON).]

Il s’agit essentiellement de la partie principale de cette fonctionnalité : Adaptateur + Service métier qui envoie des messages avec les modifications apportées à une collection de bases de données Mongo.

Élargir le tableau 👩‍⚕️

À des fins de démonstration et pour créer un flux complet qui « raconte une histoire » (ce qui était le cas d'utilisation réel que j'avais), j'ai également ajouté une cible pour ce CDC, qui est une API REST d'un Dossier Patient Informatisé (DPI ou EMR pour Electronic Medical Record) fictif, qui prend les données des patients et les insère dans une table de patients.

Vous trouverez cette partie sous le package Demo.EMR (Data.Patient pour la table et Util.API pour l'API REST) ; et le package Demo.Int pour la partie Opérations métiers.

En fait, vous pouvez réutiliser cette partie pour tout autre besoin que vous pourriez rencontrer lorsque vous avez besoin d'une API fictive pour envoyer des données de patient à des fins de test en tant que destination cible.

[Notez que la table « Mock EMR » et l'API incluent des éléments de données que je n'ai pas utilisés dans cette démonstration, comme l'adresse e-mail et le numéro de téléphone]

Un exemple de flux complet (avec captures d'écran) 📷

Voici donc un exemple de déroulement de la manière dont cela fonctionne :

1. Ajoutez un document à votre collection mongo.

 
Commandes Shell (Docker exec pour se connecter au conteneur mongo et commandes mongosh pour lancer ReplicaSet et un document vers une collection)

2. Examinez votre table « EMR » et voyez les nouvelles données de Mongo insérées dans celle-ci

 
DBeaver visualisant les données dans la table Patient

3. Examinez les « coulisses » d’InterSystems IRIS en prenant soin de ce flux

 
Trace visuelle du flux de messages

Faites l'essai de votre côté🏎

L'application Open Exchange inclut tout le code associé et les instructions de configuration pour une démonstration complète basée sur le conteneur Docker comme indiqué ci-dessus (avec toutes les parties associées, y compris les conteneurs Mongo).

[Remarque : Mongo a une notion de ReplicaSet et c'est seulement avec cette fonctionnalité que change_streams fonctionne. Pour plus de simplicité, la démonstration ci-dessus suppose que mongo1 (il y a aussi mongo2 et mongo3) est le « principal »].

Encore une fois, ce n’est qu’un exemple de la manière dont Embedded Python peut vous permettre de relever vos défis d’interopérabilité très rapidement et facilement.

Discussion (0)1
Connectez-vous ou inscrivez-vous pour continuer
Question
· Fév 26

Maximum license usage

Hello everyone

I have a question about the maximum number of active license users for CACHÉ.

When I run the command: Do $System.License.ShowCounts()

I get the following return:

1 Current active users
3 Maximum active users
0 CSP users currently active
1 Maximum active CSP users
0 CSP sessions currently in 'grace period'
1 Maximum CSP sessions in 'grace period'

I couldn't find it in the documentation, but I want to know if "3 Maximum active users" is the maximum number of users who have used the license since the period I installed the CACHÉ instance or since another period. Could you help me?

3 Comments
Discussion (3)1
Connectez-vous ou inscrivez-vous pour continuer
Discussion (1)1
Connectez-vous ou inscrivez-vous pour continuer
Article
· Fév 26 6m de lecture

The Case for IRIS and JavaScript

Introduction

My guess is that most IRIS developers create their applications using its native ObjectScript language or, if using an external language, then most likely using either Java, Python or perhaps C++.

I suspect that only a minority have considered using JavaScript as their language of choice, which, if true, is a great shame, because, In my opinion and experience, JavaScript is the closest equivalent to ObjectScript in terms of its ability to integrate with the IRIS's underlying multi-dimensional database. 

In this article I'd like to lay out the case for JavaScript as a first-class language for IRIS. You never know: I might even change a few made-up minds on the issue!

Server-Side JavaScript

JavaScript was famously written in just 10 days by Brendan Eich in 1995 for the then Netscape browser. It is now, of course, the de-facto language for client-side web applications, supported natively by all mainstream web browsers.

An early incarnation of server-side JavaScript was created by Netscape around the same time, but it wan't particularly successful.  It wasn't really until Ryan Dahl created Node.js in about 2010 that server-side JavaScript really took off and became "a thing".  More recently a serious competitor to Node.js - Bun - has emerged: its main advantage over Node.js is its stellar performance.

So, of course, when I refer to the use of JavaScript with IRIS, I'm meaning server-side JavaScript, using either Node.js or Bun.

JavaScript has many detractors: you often hear criticisms that it's somehow a "toy language" or that it has too many quirks and idiosyncrasies to make it a viable language for serious production systems.  Most of those criticisms, however, are unfounded if you take a close and serious look at JavaScript.

Yes, JavaScript does have its quirks, but they are all avoidable.  As a language, it actually has some incredibly powerful features such as closures and the ability to pass functions as arguments into other functions.  It's also got everything you need for modern event-driven programming.

It's fast - particularly when you see Bun in action.  And it's massively scalable (an interesting example: apparently the recent Superbowl portal back-end was built on Bun and handled the crazy volumes of traffic without barely breaking a sweat).

The other key benefit of server-side JavaScript is that the full front- and back-end application stack can be developed with one single language skill and resource: no need for separate teams of developers with different language skills and expertise.

Why JavaScript is a Good Fit for IRIS

IRIS Language and Data Characteristics

I won't go into historical details in this article, but I think it's fair to say that IRIS's native language - ObjectScript - was designed around the idea of an intimately close relationship between data that was in-memory and data that was on disk, with the language able to manipulate both in a near-identical way.  The native data structure is hierarchical and is conceptually identical whether that data is in-memory or on disk.  As far as the language is concerned, the only difference between an in-memory "local array" and and on-disk multi-dimensional data store (historically known as a Global) is a ^ symbol.

The native IRIS language is interpreted and is also inherently loosely-typed - everything is essentially strings or numerics.

ObjectScript is also extremely fast.

And finally, the multi-dimensional data store is schema-free.

JavaScript Language and Data Characteristics

Now let's examine the equivalent features of JavaScript.  Of course, JavaScript doesn't natively include a database (but more on that later!)

However, as a language, it has interesting similarities: it is interpreted, and is loosely-typed.  If you're comfortable working with ObjectScript's loose typing, you'll be comfortable with JavaScript's approach to types.  The strict typing zealots won't like either of course, but some of us aren't in that camp!

The native data structure of JavaScript is its Objects which are inherently hierarchical and schema-free. 

In fact JavaScript's native data structure is now ubiquitous outside of JavaScript itself: JSON is now pretty much the de-facto data interchange structure that is used whatever language you use, and yet the acronym tells you its origin: JavaScript Object Notation.  

For most/many languages, the parsing and serialisation of JSON data can be something of a struggle.  For JavaScript it's the native data structure and parsing and serialisation is fast, efficient and simple.

In terms of performance, in my experience JavaScript is on a par with IRIS ObjectScript.

JSON and Multi-Dimensional Data Storage

Whilst IRIS now has its own specialised JSON storage capability, the similarities described above actually make the mapping of all but the most complex JSON data in and out standard IRIS multi-dimensional data storage a fairly trivial and efficient exercise.  Put simply, if ever there was a database designed for the storage of JSON and persistence of JavaScript Objects, it would be IRIS! 

Making the Connection: the Challenges

So how do you use JavaScript with IRIS, and how can you achieve a seamless mapping of in-memory JavaScript Objects with on-disk JSON storage in IRIS multi-dimensional storage?  For example, would it be possible to envision a JavaScript equivalent of the ^ symbol to denote in-memory versus on-disk objects?

You can make a start by trying out the IRIS Native API for Node.js.  However, you'll discover that the integration it provides is very basic - too basic for the kind of things I'm envisioning, and, as its name implies, is limited to the use of Node.js.  It's also not a very performant interface: thereby losing and wasting most of the inherent performance of the JavaScript language.

What's needed, then, is an interface between Node.js and Bun that can access IRIS multi-dimensional storage with a similar level of performance to IRIS ObjectScript: on even relatively basic hardware that means being able to handle millions of database nodes representing key/values per second.

There's also another piece of the puzzle that needs addressing if we want to use JavaScript as a first-class language for IRIS: JavaScript is a single-threaded language.  To support concurrent use by multiple users, the standard approach is to access resources such as databases and files via asynchronous callbacks, all from a single process with a single thread of execution.  That's a very unusual architecture and a tricky bed-fellow when using the IRIS database which is designed for synchronous use from within a multi-threaded architecture for handling concurrency.

The Solutions

It's these challenges that have interested me ever since Node.js first appeared, and suffice to say they are all possible to address.  How that's done is beyond the scope of this article, but almost all my work these days involves the use of JavaScript and the use of persistent JavaScript Objects held in multi-dimensional storage and I've written lots elsewhere about how the challenges can be addressed and the resulting benefits achieved.

To me, it's all about a perfect marriage of a modern language with all sorts of incredibly powerful features, yet having all the productivity characteristics I loved about ObjectScript, with a powerful, incredibly fast and scalable schema-free database in which I can save, access, manipulate and retrieve JavaScript objects seamlessly and directly from disk.

The JavaScript equivalent of ^ to distinguish in-memory and on-disk Objects?  Yes, it can be done, and it's like magic to see it in action.

Discussion (0)2
Connectez-vous ou inscrivez-vous pour continuer