#JavaScript

0 Abonnés · 5 Publications

JavaScript, souvent abrégé en JS, est un langage de programmation interprété de niveau élevé. Il s'agit d'un langage qui est également caractérisé comme dynamique, faiblement typé, basé sur des prototypes et multi-paradigme.

En savoir plus.

Article Iryna Mykhailova · Oct 9, 2025 6m read

Aperçu

Le projet typeorm-iris fournit une prise en charge expérimentale pour l'intégration de TypeORM avec InterSystems IRIS, permettant aux développeurs d'interagir avec IRIS à l'aide des décorateurs et des abstractions de référentiel bien connus de TypeORM. Cela offre une expérience de développement plus familière aux développeurs JavaScript et TypeScript qui créent des applications Node.js avec IRIS comme base de données backend.

Aperçu de TypeORM MongoDB. J'ai récemment commencé à utiliser TypeORM dans… | Eliezer  Steinbock | Medium

Bien que le projet mette en œuvre des éléments clés d'intégration avec TypeORM et prenne en charge les opérations de base sur les entités, il n'a pas encore été testé en conditions réelles et n'est pas adapté aux environnements de production.

Pourquoi typeorm-iris?

Le pilote officiel InterSystems IRIS Node.js ne permet pas d'exécuter des requêtes SQL natives , contrairement à d'autres pilotes de base de données (par exemple, PostgreSQL ou MySQL). Au lieu de cela, vous devez utiliser une API basée sur ObjectScript (par exemple, %SQL.Statement) pour préparer et exécuter les commandes SQL.

Cela pose problème lors du développement d'applications modernes qui s'appuient sur des outils de mappage objet-relationnel (ORM) tels que TypeORM. TypeORM nécessite un pilote de niveau inférieur capable de préparer et d'exécuter du code SQL brut dans une seule session de connexion, ce qui n'est actuellement pas possible avec les outils JavaScript d'IRIS.

Pour surmonter ces limitations, typeorm-iris implémente les éléments nécessaires pour faire le pont entre IRIS et TypeORM, en utilisant les interfaces d'exécution SQL ObjectScript disponibles en arrière-plan.

Phase initiale & problèmes connus

Ce projet en est à la phase initiale et n'a été testé que sur quelques cas. Il faut s'attendre à une certaine instabilité, à des fonctionnalités manquantes et à des changements importants dans les prochaines versions.

Les limitations importantes observées au cours du développement sont les suivantes:

1. Allers-retours excessifs en réseau

L'exécution de SQL via la classe %SQL.Statement à partir de JavaScript implique plusieurs messages réseau entre le processus Node.js et le serveur IRIS. Par exemple, une seule opération SQL logique peut nécessiter plusieurs étapes, telles que:

  • Preparation de l'instruction
  • Exécution de la requête
  • Récupération des métadonnées
  • Récupération de lignes de manière individuelle

Chacun d'entre eux peut générer des messages distincts sur le réseau, ce qui entraîne une surcharge considérable par rapport à l'utilisation d'un pilote SQL natif.

2. Aucune prise en charge de l'asynchronisme/du parallélisme véritable

Le pilote IRIS Node.js officiel ne prend pas en charge l'utilisation asynchrone dans un contexte multithread ou basé sur le travail:

  • La reconnexion dans le même processus échoue souvent ou provoque un comportement imprévisible.
  • La création de threads de travail et l'utilisation du pilote à l'intérieur de ceux-ci entraînent des problèmes.
  • Que une seul connexion par processus fonctionne de manière fiable.

Ces contraintes rendent ce système inadapté aux applications Node.js modernes qui traitent des tâches simultanées. Cette situation limite considérablement la capacité du pilote à s'adapter à des charges de travail simultanées et restreint considérablement les choix architecturaux.

Guide d'utilization

En raison de l'utilisation des dernières fonctionnalités IRIS SQL, il est nécessaire de disposer d'IRIS 2025.1+ pour fonctionner.

Vous pouvez installer typeorm-iris avec npm:

npm install typeorm-iris

Comme ce pilote n'est pas officiellement pris en charge par TypeORM, son utilisation nécessite une solution de remplacement pour configurer le DataSource. Vous ne pouvez pas utiliser directement new DataSource() ou createConnection() comme vous le feriez avec les pilotes officiels.

Configuration personnalisée de la source de données

import { IRISDataSource, IRISConnectionOptions } from "typeorm-iris"

const dataSourceOptions: IRISConnectionOptions = { name: "iris", type: "iris", host: "localhost", port: 1972, username: "_SYSTEM", password: "SYS", namespace: "USER", logging: true, dropSchema: true, }

export function createDataSource(options: any): IRISDataSource { // @ts-ignore const dataSource = new IRISDataSource({ ...dataSourceOptions, ...options }) return dataSource }

Lorsque l'initialisation est terminée, vous pouvez utiliser les décorateurs TypeORM comme d'habitude:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"

@Entity() export class User { @PrimaryGeneratedColumn() id: number

@Column()
name: string

@Column()
email: string

}

Il en va de même pour les référentiels:

const userRepository = dataSource.getRepository(User)
const newUser = userRepository.create({ name: "Alice", email: "alice@example.com" })
await userRepository.save(newUser)

Exemples de projets

Le référentiel GitHub comprend un dossier sample/ qui contient plusieurs exemples fonctionnels:

  • sample1-simple-entity
  • sample2-one-to-one
  • sample3-many-to-one
  • sample4-many-to-many
  • sample16-indexes

Celles-ci traitent des fonctionnalités de base en matière de persistance, de relations et de schémas, et présentent des exemples d'utilisation pratique.

Tests unitaires

Les tests initiaux comprennent les cas d'utilisation suivants :

Modèle d'entité

  • doit enregistrer et utiliser de manière appropriée les méthodes statiques
  • doit recharger correctement l'entité donnée
  • doit recharger exactement la même entité
  • doit effectuer correctement un upsert

Schéma d'entité > Index

  • basique

Persistance

  • fonctionnalité basique
  • mise à jour d'entité
  • insertion > update-relation-columns-after-insertion (mise à jour des colonnes de relation après insertion)
  • plusieurs-à-plusieurs
  • en individuel

Ces tests ont une portée limitée et leur couverture sera élargie au fur et à mesure de l'avancement du projet.

Fonctionnalités prises en charge

  • Décorateurs d'entités: @Entity(), @Column(), @PrimaryGeneratedColumn()
  • Référentiels: create, save, find, delete, etc.
  • Suppression et synchronisation du schéma (expérimental)
  • Prise en charge partielle des relations et des requêtes personnalisées

Attention, ces fonctionnalités sont encore en phase initiale et peuvent ne pas couvrir l'ensemble des capacités de TypeORM.

Limitations réelles

Limitations liées au pilote Node.js d'InterSystems IRIS

  • Une seule connexion utilisable par processus
  • Pas de prise en charge adéquate des opérations parallèles ou du threading
  • Absence de prise en charge native de l'API SQL (via le protocole SQL)
  • Dépendance importante à la communication par messages utilisant un protocole propriétaire

Tant qu'InterSystems n'aura pas mis à jour le pilote officiel afin d'assurer la prise en charge de l'exécution SQL et des opérations simultanées, ce projet restera très limité en termes de performances et d'évolutivité.

Commentaires & Contributions

Comme il s'agit d'un pilote expérimental, vos commentaires sont essentiels. Que vous l'essayiez pour un petit projet parallèle ou que vous l'évaluiez en vue d'une utilisation plus large, n'hésitez pas à partager vos problèmes et suggestions sur GitHub:

➡️ github.com/caretdev/typeorm-iris/issues

Les pull requests, les cas de test et les améliorations de la documentation sont appréciés.

À venir

Les améliorations prévues incluent:

  • Élargissement de la couverture des tests pour les requêtes réelles et les conceptions de schémas
  • Prise en charge d'un plus grand nombre de fonctionnalités du générateur de requêtes TypeORM
  • Analyse des optimisations par lots
  • Amélioration de l'introspection des schémas pour les migrations

Conclusion

typeorm-iris apporte un soutien indispensable de TypeORM à InterSystems IRIS pour les développeurs Node.js. Bien qu'il ne soit pas encore prêt pour la production et qu'il hérite des limitations importantes de l'infrastructure actuelle du pilote, il constitue une base pour poursuivre l'expérimentation et potentiellement élargir son adoption au sein de la communauté des développeurs IRIS.

Si vous êtes un développeur IRIS et cherchez à intégrer un backend Node.js moderne à l'aide de TypeORM, c'est le point de départ idéal.

Et si vous avez trouvé cela utile, n'hésitez pas à voter à pour cette solution dans le concours InterSystems Developer Tools Contest!

0
0 11
Article Pierre LaFay · Mars 3, 2024 9m read

Intro

La plupart des communications serveur-client sur le web sont basées sur une structure de demande et de réponse. Le client envoie une demande au serveur et le serveur répond à cette demande. Le protocole WebSocket fournit un canal de communication bidirectionnel entre un serveur et un client, permettant aux serveurs d'envoyer des messages aux clients sans recevoir de demande au préalable. Pour plus d'informations sur le protocole WebSocket et son implémentation dans InterSystems IRIS, voir les liens ci-dessous.

Ce tutoriel est une mise à jour de ["Asynchronous Websockets -- a quick tutorial"] (https://community.intersystems.com/post/asynchronous-websockets-quick-tutorial) pour Caché 2016.2+ et InterSystems IRIS 2018.1+.

Fonctionnement asynchrone ou synchrone

Dans InterSystems IRIS, une connexion WebSocket peut être mise en œuvre de manière synchrone ou asynchrone. Le mode de fonctionnement de la connexion WebSocket entre le client et le serveur est déterminé par la propriété "SharedConnection" de la classe %CSP.WebSocket.

  • SharedConnection=1 : Fonctionnement asynchrone

  • SharedConnection=0: Fonctionnement synchrone

Une connexion WebSocket entre un client et un serveur hébergé sur une instance InterSystems IRIS comprend une connexion entre l'instance IRIS et la passerelle Web. En mode synchrone, la connexion utilise un canal privé. Dans le cas d'une opération WebSocket asynchrone, un groupe de clients WebSocket partage un pool de connexions entre l'instance IRIS et la passerelle Web. L'avantage d'une implémentation asynchrone des WebSockets est évident lorsque de nombreux clients se connectent au même serveur, car cette implémentation n'exige pas que chaque client soit traité par une connexion exclusive entre la passerelle Web et l'instance IRIS.

Dans ce tutoriel, nous mettrons en œuvre les WebSockets de manière asynchrone. Ainsi, toutes les fenêtres de chat ouvertes partagent un pool de connexions entre la passerelle Web et l'instance IRIS qui héberge la classe de serveur WebSocket.

Présentation de l'application Chat

Le "hello world" des WebSockets est une application de chat dans laquelle un utilisateur peut envoyer des messages qui sont diffusés à tous les utilisateurs connectés à l'application. Dans ce tutoriel, les composants de l'application de chat sont les suivants :

  • Serveur : implémenté dans une classe qui étend %CSP.WebSocket

  • Client: mis en œuvre par une page CSP

La mise en œuvre de cette application de chat permettra d'atteindre les objectifs suivants :

  • Les utilisateurs peuvent diffuser des messages à toutes les fenêtres de chat ouvertes

  • Les utilisateurs en ligne apparaissent dans la liste "Utilisateurs en ligne" de toutes les fenêtres de chat ouvertes.

  • Les utilisateurs peuvent changer leur nom d'utilisateur en composant un message commençant par le mot-clé "alias". Ce message ne sera pas diffusé mais mettra à jour la liste des "Utilisateurs en ligne".

  • Lorsque les utilisateurs ferment leur fenêtre de chat, ils sont retirés de la liste des "Utilisateurs en ligne".

Pour obtenir le code source de l'application de chat, veuillez consulter ce [dépôt GitHub] (https://github.com/intersystems/InterSystems-WebSockets).

Le Client

Le côté client de notre application de chat est mis en œuvre par une page CSP contenant le style de la fenêtre de chat, la déclaration de la connexion WebSocket, les événements et méthodes WebSocket qui gèrent la communication vers et depuis le serveur, et les fonctions d'aide qui regroupent les messages envoyés au serveur et traitent les messages entrants.

Tout d'abord, nous verrons comment l'application initie la connexion WebSocket à l'aide d'une bibliothèque Javascript WebSocket.

    ws = new WebSocket(((window.location.protocol === "https:")? "wss:":"ws:")
                    + "//"+ window.location.host + "/csp/user/Chat.Server.cls");

new crée une nouvelle instance de la classe WebSocket. Celle-ci ouvre une connexion WebSocket au serveur en utilisant le protocole "wss" (indique l'utilisation de TLS pour le canal de communication WebSocket) ou "ws". Le serveur est spécifié par le numéro de port du serveur web et le nom de l'hôte de l'instance qui définit la classe Chat.Server (cette information est contenue dans la variable window.location.host). Le nom de notre classe de serveur (Chat.Server.cls) est inclus dans l'URI d'ouverture de la WebSocket en tant que requête GET pour la ressource sur le serveur.

L'événement ws.onopen se déclenche lorsque la connexion WebSocket est établie avec succès, passant d'un état connecting à un état open.

    ws.onopen = function(event){
        document.getElementById("headline").innerHTML = "CHAT - CONNECTED";
    };

Cet événement met à jour l'en-tête de la fenêtre de chat pour indiquer que le client et le serveur sont connectés.

Envoi de messages

L'action d'un utilisateur qui envoie un message déclenche la fonction send. Cette fonction sert d'enveloppe à la méthode ws.send, qui contient les mécanismes d'envoi du message du client au serveur via la connexion WebSocket.

function send() {
	var line=$("#inputline").val();
	if (line.substr(0,5)=="alias"){
	    alias=line.split(" ")[1];
		if (alias==""){
		    alias="default";
		}
		var data = {}
		data.User = alias
		ws.send(JSON.stringify(data));
        } else {
	    var msg=btoa(line);
	    var data={};
	    data.Message=msg;
	    data.Author=alias;
	    if (ws && msg!="") {
		    ws.send(JSON.stringify(data));
	    }
	}
	$("#inputline").val("");
}

send compile les informations à envoyer au serveur dans un objet JSON, en définissant des paires clé/valeur en fonction du type d'information envoyée (mise à jour d'alias ou message général). btoa traduit le contenu d'un message général en une chaîne ASCII encodée en base 64.

Réception des messages

Lorsque le client reçoit un message du serveur, l'événement ws.onmessage est déclenché.

ws.onmessage = function(event) {
	var d=JSON.parse(event.data);
	if (d.Type=="Chat") {
	    $("#chat").append(wrapmessage(d));
            $("#chatdiv").animate({ scrollTop: $('#chatdiv').prop("scrollHeight")}, 1000);
	} else if(d.Type=="userlist") {
		var ul = document.getElementById("userlist");
		while(ul.firstChild){ul.removeChild(ul.firstChild)};
		$("#userlist").append(wrapuser(d.Users));
	} else if(d.Type=="Status"){
		document.getElementById("headline").innerHTML = "CHAT - connected - "+d.WSID;
	}
};

Selon le type de message reçu par le client ("Chat", "userlist" ou "status"), l'événement onmessage appelle wrapmessage ou wrapuser pour remplir les sections appropriées de la fenêtre de chat avec les données entrantes. Si le message entrant est une mise à jour d'état, l'en-tête d'état de la fenêtre de discussion est mis à jour avec l'ID WebSocket, qui identifie la connexion WebSocket bidirectionnelle associée à la fenêtre de discussion.

Composants supplémentaires du client

Une erreur dans la communication entre le client et le serveur déclenche la méthode WebSocket onerror, qui émet une alerte nous informant de l'erreur et mettant à jour l'en-tête d'état de la page.

ws.onerror = function(event) {
	document.GetElementById("headline").innerHTML = "CHAT - error";
	alert("Received error"); 
};

The onclose method is triggered when the WebSocket connection between the client and server is closed and updates the status header.

ws.onclose = function(event) {
	ws = null;
	document.getElementById("headline").innerHTML = "CHAT - disconnected";
}

Le Serveur

Le côté serveur de l'application de chat est implémenté par la classe Chat.Server, qui étend %CSP.WebSocket. Notre classe serveur hérite de diverses propriétés et méthodes de %CSP.WebSocket, dont certaines seront discutées ci-dessous. Chat.Server implémente également des méthodes personnalisées pour traiter les messages provenant du ou des client(s) et pour les diffuser.

Avant de démarrer le serveur

OnPreServer() est exécutée avant la création du serveur WebSocket et est héritée de la classe %CSP.WebSocket.

Method OnPreServer() As %Status
{
    set ..SharedConnection=1
    if (..WebSocketID '= ""){ 
        set ^Chat.WebSocketConnections(..WebSocketID)=""
    } else {
        set ^Chat.Errors($INCREMENT(^Chat.Errors),"no websocketid defined")=$HOROLOG 
    }
    Quit $$$OK
}

Cette méthode définit le paramètre de classe SharedConnection à 1, indiquant que notre connexion WebSocket sera asynchrone et supportée par plusieurs processus qui définissent les connexions entre l'instance InterSystems IRIS et la Web Gateway. Le paramètre SharedConnection ne peut être modifié que dans OnPreServer(). OnPreServer() stocke également l'identifiant WebSocket associé au client dans le global ^Chat.WebSocketConnections.

La méthode Server

L'essentiel de la logique exécutée par le serveur est contenu dans la méthode Server().``` Method Server() As %Status { do ..StatusUpdate(..WebSocketID) for { set data=..Read(.size,.sc,1) if ($$$ISERR(sc)){ if ($$$GETERRORCODE(sc)=$$$CSPWebSocketTimeout) { //$$$DEBUG("no data") } if ($$$GETERRORCODE(sc)=$$$CSPWebSocketClosed){ kill ^Chat.WebSocketConnections(..WebSocketID) do ..RemoveUser($g(^Chat.Users(..WebSocketID))) kill ^Chat.Users(..WebSocketID) quit // Client closed WebSocket } } else{ if data["User"{ do ..AddUser(data,..WebSocketID) } else { set mid=$INCREMENT(^Chat.Messages) set ^Chat.Messages(mid)=data do ..ProcessMessage(mid) } } } Quit $$$OK }

Cette méthode lit les messages entrants du client (en utilisant la méthode `Read` de la classe `%CSP.WebSockets`), ajoute les objets JSON reçus au global `^Chat.Messages`, et appelle `ProcessMessage()` pour transmettre le message à tous les autres clients de chat connectés. Lorsqu'un utilisateur ferme sa fenêtre de chat (mettant ainsi fin à la connexion WebSocket avec le serveur), l'appel à `Read` de la méthode `Server()` renvoie un code d'erreur qui évalue la macro `$$CSPWebSocketClosed` et la méthode procède à la gestion de la fermeture en conséquence.

### *Traitement et distribution des messages*

`ProcessMessage()` ajoute des métadonnées au message de chat entrant et appelle `SendData()`, en passant le message en paramètre.  

ClassMethod ProcessMessage(mid As %String) { set msg = ##class(%DynamicObject).%FromJSON($GET(^Chat.Messages(mid))) set msg.Type="Chat" set msg.Sent=$ZDATETIME($HOROLOG,3) do ..SendData(msg) }


`ProcessMessage()` récupère le message au format JSON dans le global `^Chat.Messages` et le convertit en un objet IRIS d'InterSystems en utilisant la méthode `%FromJSON` de la classe `%DynamicObject`. Cela nous permet d'éditer facilement les données avant de transmettre le message à tous les clients de chat connectés. Nous ajoutons un attribut `Type` avec la valeur "Chat", que le client utilise pour déterminer comment traiter le message entrant. `SendData()` envoie le message à tous les autres clients de chat connectés.```
ClassMethod SendData(data As %DynamicObject)
{
    set c = ""
    for {
        set c = $order(^Chat.WebSocketConnections(c))
        if c="" Quit
        set ws = ..%New()
        set sc = ws.OpenServer(c)
        if $$$ISERR(sc) { do ..HandleError(c,"open") } 
        set sc = ws.Write(data.%ToJSON())
        if $$$ISERR(sc) { do ..HandleError(c,"write") }
    }
}

SendData() convertit l'objet InterSystems IRIS en une chaîne JSON (data.%ToJSON()) et envoie le message à tous les clients du chat. SendData() récupère l'ID WebSocket associé à chaque connexion client-serveur dans le global ^Chat.WebSocketConnections et utilise l'ID pour ouvrir une connexion WebSocket via la méthode OpenServer de la classe %CSP.WebSocket. Nous pouvons utiliser la méthode OpenServer car nos connexions WebSocket sont asynchrones - nous puisons dans le pool existant de processus IRIS-Web Gateway et attribuons à l'un d'entre eux l'ID WebSocket qui identifie la connexion du serveur à un client de chat spécifique. Enfin, la méthode Write()%CSP.WebSocket` envoie la représentation JSON du message au client.

Conclusion

Cette application de chat montre comment établir des connexions WebSocket entre un client et un serveur hébergés par InterSystems IRIS. Pour en savoir plus sur le protocole et son implémentation dans InterSystems IRIS, consultez les liens dans l'introduction.

0
0 199
Question Cyril Grosjean · Nov 15, 2023

Bonjour,

Dans le besoin de notre service infrastructure de notre entreprise, j'ai créé une petite API qui fait des requêtes SNMP sur InterSystems afin de visualiser les données intéressantes à récupérer lorsque l'infra mettra en place le monitoring.

Cependant, j'ai un timeout lorsque j'essaye de collecter des informations via un walk. Voici le code du service SNMP de mon API:

7
0 111
Article Lorenzo Scalese · Sept 9, 2022 3m read

Salut mes amis,

C'est le concours FHIR et cette fois, ils ont fourni quelque chose de vraiment cool : FHIRaaS

Et pour faire partie de cela, @José Pereira et moi faisons équipe (encore une fois) pour livrer quelque chose de facile à utiliser et facile à comprendre ce que nous avons fait.

Qu'avons-nous fait ?

IRIS sur FHIR : une application SMART pour montrer le potentiel de FHIRaaS en utilisant la bibliothèque client SMART JS

Description de l'application

IRIS on FHIR, c'est notre idée de la facilité et de la simplicité avec laquelle on peut travailler avec FHIR, en créant une grande interface utilisateur pour montrer la puissance de FHIRaaS.

Nous espérons que notre projet permettra à tout le monde de mieux comprendre ; nous voulons partager les connaissances et montrer que quelque chose de bien n'est pas nécessairement compliqué.

Et comme il est facile à comprendre et à utiliser, nous pensons que notre projet peut être utilisé comme base/exemple pour beaucoup d'autres, débloquant ainsi de plus en plus de fonctionnalités.

À quoi ressemble IRIS sur FHIR

Liste des patients

Cette page est une liste des patients utilisant la ressource Patient.

Le tableau de données reconnaît le tableau fourni pour la ressource Patient et montre quelques informations sur le patient.

Liste des patients

Vue du patient

En cliquant sur le lien Prénom du patient, vous serez redirigé vers la page Vue du patient. Cette page contient plus d'informations sur ce patient.

Vue du patient

En haut, nous avons la photo du patient, son ID FHIR, son SSN, sa date de naissance, son sexe, son contact, son adresse, sa ville, son pays.

La partie centrale fournit des cartes à deux sections :

  • Dernière admission
  • Dernières observations : Laboratoire

Les badge-pills des composants apportent le total des cartes respectives.

badge-pill

Pour la carte Observations:Laboratoire, les badge-pills ouvrent une nouvelle page présentant les résultats du laboratoire.

Résultats du laboratoire

Choisissez l'une des options dans la boîte de sélection Select box, cliquez sur le bouton de recherche Search, et vous obtiendrez le tableau avec les valeurs du test de laboratoire sélectionné.

Tests de laboratoire

Choisissez l'une des options dans la boîte de sélection Select box, cliquez sur le bouton de recherche Search, et vous obtiendrez le tableau avec les valeurs du test de laboratoire sélectionné.

Résultats des tableaux

Rendez-vous

Les rendez-vous sont affichés dans la vue du calendrier, et les informations sont chargées via la ressource FHIR : Rendez-vous. Calendrier des rendez-vous

Vous pouvez également créer de nouveaux rendez-vous, les mettre à jour et les supprimer.

CRUD des rendez-vous

Demo

https://iris-on-fhir.contest.community.intersystems.com/iris-on-fhir/index.html

  • utilisateur: irisonfhir
  • mot de passe: irisonfhirA1@

Si vous avez aimé l'application et pensez que nous méritons votre vote, veuillez voter pour iris-on-fhir !

https://openexchange.intersystems.com/contest/current

0
0 92