· Sep 12, 2020

Calling a classmethod of an instance from another instance via native method

Dear Folks,

I am looking for a native approach to call a ClassMethod of an instance from another instance (Instances are running in different servers).  I can still do this via API over Http or any other communication method but I believe it would be better if I communicate via IRIS native methods(If exists).


Discussion (14)1
Log in or sign up to continue

If you're using IRIS 2020.2.0 or above (both target and source instances must be ^2020.2.0), you can try to leverage %Net.DB.Iris. It's an implementation of IRIS Native for Java/.NET/Python/Node except for Objectscript. If there is enough interest for features like %Net.DB.Iris, @Bob Kuszewski would love to hear about it and communicate that interest over to the development teams!

some ideas from the hip:

  • classic SOAP service
  • running a background job over ECP
  • having a listening job that triggers whatever you need
  •  using WebSocket communications

They all run over TCP as there is nothing else between separated servers.
At the bottom line, you rely on some code expecting a request.
"Native API" for various languages, or Studio, or CSP do the same over Super Server Port (1972) 
the quality is different, not the principle.

Let me focus on the last two items in your list. IRIS Native for Java, Node.js, DotNet, Python - these are all consistent implementations of the IRIS Native API and the communication is over TCP or shared memory. IRIS Native for ObjectScript is just another - consistent - implementation of the IRIS Native API.

To get a connection to an IRIS server, the command is similar across all implementations of IRIS Native API:

set connection = ##class(%Net.DB.DataSource).CreateConnection(host, port, namespace, user, pwd)

Once you have a connection, you can get an IRIS object.

set iris = connection.CreateIris()

and from an iris object, you can invoke class methods, code implemented in routines, set/get globals, and so on.

That is a good question! I checked the internal change logs and found my changes were in 2020.1. Maybe earlier but I installed 2020.1 build 215 and tested a simple case.

IRIS for UNIX (Apple Mac OS X for x86-64) 2020.1 (Build 215U) Mon Mar 30 2020 20:24:45 EDT

The test is simple - I am running in the 2020R1 instance, namespace USER and there are no classes runnable in this namespace - just a clean, new install. I have several other instances running, all different versions/build numbers. I am testing against my XDBC instance which is currently labeled as 2020.4 (obviously not yet released but the IRIS Native code is essentially the same as in 2020.1). The XDBC instance is listening on port 51780. First, proof this doesn't work locally.

USER>write ##class(Sample.Person).CurrentAge($h-35000)                 

WRITE ##CLASS(Sample.Person).CurrentAge($H-35000)

And then, attempt the same function using the IRIS Native connection to the XDBC instance.

USER>set host="localhost",port=51780,namespace="USER",user="_SYSTEM",pwd="SYS" 

USER>set connection = ##class(%Net.DB.DataSource).CreateConnection(host, port, namespace, user, pwd)

USER>set iris = connection.CreateIris()                                                             

USER>write iris.ClassMethodValue("Sample.Person","CurrentAge",$h-35000)                             

This is just a sample. Browse the classes in the SMP Explorer, look at the class docs for %Net.DB.Iris.cls.

This functionality might also be present in a 2019 kit but I didn't test it.

If the servers can 'see' each other . Lets call then Server A with Namespace A and Server B with Namespace B. You do the following:

1) From the Management Portal on Server A use the System->Configuration->ECP Settings->ECP Data Servers and Add a new Server connection to Server B

2) Then within the System Configuration use the Add Remote Database to create a Database definition of the Database or Databases that Namespace B uses (Typically a namespace will be linked to one database that contains both the Application Code (Classes and Routines) and the Application Data (Globals). However it is also possible that the Application Classes and Routines live in one database and the data in another. 

3) On Server A create a new Namespace that links to the Database(s) you have mapped in step (2)

4) In the Namespace Definition of Namespace A on Server A use the Package Mapping to Map the class, selection of classes or class package into Namespace A. If the class you want to interact with is linked to an underlying Global Definition (Data, Index and Stream) then use the Global Mapping to Map the Globals used by the class into Namespace A

5) The Class (call it {PackageB}.[ClassNameB} will now appear as a class in Namespace A and if you run the methods in {PackageB}.{ClassNameB} then the code will execute in the Cache Job on Server A but any data retrievals or saves will be executed in the global(s) in the Global Database of Namespace B on Server B

There may be licensing implications to use ECP but I am not an expert on current InterSystems licensing models

The other way would be to expose the methods of Class B in Namespace B on Server B in the form of a Web Service on Server B and then invoke the methods from Server A by invoking HTTP calls to the Web Service.