NODE.JS and GT.m

247 views
Skip to first unread message

Ben Irwin

unread,
Jun 13, 2020, 7:37:02 PM6/13/20
to Hardhats
I have been working with node.js and gtm.  I have come up with an easy and tight connection between the two.  I have come to the conclusion that working with node.js and gtm is so much simpler then understanding Medicare and Social Security.

Sam Habiel

unread,
Jun 13, 2020, 7:48:23 PM6/13/20
to hardhats
> I have come to the conclusion that working with node.js and gtm is so much simpler then understanding Medicare and Social Security.
I am sure you are right.

--Sam

On Sat, Jun 13, 2020 at 7:37 PM Ben Irwin <ben1...@gmail.com> wrote:
>
> I have been working with node.js and gtm. I have come up with an easy and tight connection between the two. I have come to the conclusion that working with node.js and gtm is so much simpler then understanding Medicare and Social Security.
>
> --
> --
> http://groups.google.com/group/Hardhats
> To unsubscribe, send email to Hardhats+u...@googlegroups.com
>
> ---
> You received this message because you are subscribed to the Google Groups "Hardhats" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to hardhats+u...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/hardhats/32bd7cef-e29c-461e-90e2-b6954b669c85o%40googlegroups.com.

K.S. Bhaskar

unread,
Jun 13, 2020, 9:30:13 PM6/13/20
to Hardhats
Before I became old and decrepit, and fell into the arms of Medicare, I had traditional insurance from my company with just one insurance card. Now I have three, a Medicare card, a Medigap card, and a prescription drug card. Three is of course simpler than one!

Regards
– Bhaskar

Ben Irwin

unread,
Jun 13, 2020, 10:54:48 PM6/13/20
to Hardhats


On Saturday, June 13, 2020 at 7:37:02 PM UTC-4, Ben Irwin wrote:
I have been working with node.js and gtm.  I have come up with an easy and tight connection between the two.  I have come to the conclusion that working with node.js and gtm is so much simpler then understanding Medicare and Social Security.

And don't forget Medicare Advantage that I think covers all three, but you have to get the individual set, before you are allowed to move to Medicare Advantage.

I am a little old and grew up with CGI scripts, so that is where I am coming from with the following code.  I am following something that I did back a few years ago that is shared at the following link.  The big difference is that I am using node.js to replace the CGI script.


The following node.js code is used to serve up a web page that runs a M routine that sets a global, reads from the global, runs an intrinsic GT.m routine, and writes the information to the web page.

The top portion should look familiar, in that I set up all the system variable to make GT.m happy.  I have three entry points that are used for no parameters, one parameter, or two parameters.

The stdout value is used to write the information from the M routine to the web page.

node.js script

var express = require("express");
var app = express();
var exec = require("child_process").exec;

process.chdir('/home/parallels');
process.env.gtm_dist = '/usr/lib/fis-gtm/V63012';
process.env.gtmdir = '.fis-gtm';
process.env.gtmver = 'V6.3-012_x86_64';
process.env.gtmroutines = '/home/parallels/.fis-gtm/V6.3-012_x86_64/o(/home/parallels/.fis-gtm/V6.3-012_x86_64/r) /usr/lib/fis-gtm/V63012';          
process.env.gtmgbldir = '/home/parallels/.fis-gtm/V6.3-012_x86_64/g/gtm.gld';
process.env.PATH = process.env.PATH + ':/usr/lib/fis-gtm/V63012';

app.get('/test', function (request, response) { test(request, response); });
app.get('/test/:param1', function (request, response) { test(request, response); });
app.get('/test/:param1/:param2', function (request, response) { test(request, response); });

var server = app.listen(8080, function(){ console.log(Date() + ": Server has started."); });

// Function to Call a M Routine through the Linux shell.
function test(request, response)
  {
    process.env.param1 = request.params.param1;
    process.env.param2 = request.params.param2;
    cmdLine = "mumps -run TEST";
    exec(cmdLine, {maxBuffer: 1024 * 3000}, function(error, stdout, stderr)
      {
      response.writeHead(200, {"Content-Type": "text/html"});
      response.write('<!DOCUMENT html>' + "\n");
      response.write('<html>' + "\n");
      response.write('<head>' + "\n");
      response.write('  <meta charset="UTF-8">' + "\n");
      response.write('  <meta http-equiv="X-UA-Compatible" content="IE=9">' + "\n");
      response.write('  <meta name="viewport" content="width=device-width, initial-scale=1">' + "\n");
      response.write('  <title>Show Directory</title>' + "\n");
      response.write('</head>' + "\n");
      response.write('<body>' + "\n");
      response.write('<pre>' + "\n");
      response.write(stdout);
      response.write('</pre>' + "\n");
      response.write('</body>' + "\n");
      response.write('</html>' + "\n");
      response.end();
      });
  }

M Routine

TEST
 New XX,PARAM1
 Set ^TIME(1)=$H
 Write "This is a test routine at $H time: ",$Get(^TIME(1)),!
 Write "Date: " Do ^%D Write !
 Set XX=$ZTRNLNM("gtmgbldir") Write "gtmgbldir variable: ",XX,!
 Set PARAM1=$ZTRNLNM("param1") Write "PARAM1: ",PARAM1,!
 Set PARAM2=$ZTRNLNM("param2") Write "PARAM2: ",PARAM2,!
 Write "Last Line",!
 Quit

Starting the nodejs service:


[parallels@localhost nodejs]$ node test.js

Sat Jun 13 2020 22:41:18 GMT-0400 (Eastern Daylight Time): Server has started.


The results for no parameter:


This is a test routine at $H time: 65543,81830
Date: 13-JUN-20
gtmgbldir variable: /home/parallels/.fis-gtm/V6.3-012_x86_64/g/gtm.gld
PARAM1: undefined
PARAM2: undefined
Last Line

The results for one parameter:

http://linux.local:8080/test/param1variable

This is a test routine at $H time: 65543,81894
Date: 13-JUN-20
gtmgbldir variable: /home/parallels/.fis-gtm/V6.3-012_x86_64/g/gtm.gld
PARAM1: param1variable
PARAM2: undefined
Last Line

The results for two parameters:

http://linux.local:8080/test/param1variable/param2variable

This is a test routine at $H time: 65543,81959
Date: 13-JUN-20
gtmgbldir variable: /home/parallels/.fis-gtm/V6.3-012_x86_64/g/gtm.gld
PARAM1: param1variable
PARAM2: param2variable
Last Line

Chattanooga Tennessee has become an Epic town, but my physician is always complaining about the very slow ICD-10 lookup functionality.  So my goal with this is to create a node.js front end that can be used with a FileMan file and see how fast I can get the lookup functionality to work.  I plan to index all the words in each ICD-10 definition, and use that index allow the user to type in multiple words for the lookup.  The AJAX style lookup will trigger on the first work, then limit by each successive word.

It sounds like a possible fast plan.  I will let you know when it's done and if it actually is fast.

I also think the the same functionality could be used for the NPI (National Provider Index) lookup.

rtweed

unread,
Jun 15, 2020, 6:27:10 AM6/15/20
to Hardhats
Why reinvent the wheel when there's both NodeM and mg-dbx for integrating Node.js and GT.M (and YottaDB)?

Ben Irwin

unread,
Jun 15, 2020, 9:20:20 AM6/15/20
to Hardhats
Because with all the time off that I am having, I have the time to explore how the wheel was made and to attempt to make a better wheel ( or one that is easier for me to understand).  My personal direction is MUMPS first, other languages as needed.  The current wheels appear to be less MUMPS.  I like the MUMPS language and the MUMPS database.


On Saturday, June 13, 2020 at 7:37:02 PM UTC-4, Ben Irwin wrote:

rtweed

unread,
Jun 15, 2020, 9:40:47 AM6/15/20
to Hardhats
The NodeM APIs, which are based on the original cache.node APIs designed by my co-director Chris Munt, are all very much Mumps Global centric, and it even gives you access to functions and procedures so you can write all your logic in Mumps code if you really want...but if that's what you want to do, I'm not sure what your purpose is for using Node.js?

It's up to you I guess :-)

Ben Irwin

unread,
Jun 15, 2020, 10:03:54 AM6/15/20
to Hardhats
The node.js portion makes the MUMPS process web accessible.  It does "seem" to be faster and more responsive than an Apache web server and CGI scripts.  I will be actually testing the speed later in my process.
As a side note, in 1974 I bought a bike frame from a great English bike builder REW Reynolds, near Kettering, England.  I build my own wheels, laced the spokes myself.  I am still riding on those wheels. 

Ben Irwin

unread,
Jun 15, 2020, 10:05:34 AM6/15/20
to Hardhats
I am using node.js because it's what the cool kids want to use.

K.S. Bhaskar

unread,
Jun 15, 2020, 10:12:36 AM6/15/20
to Hardhats
Ben, I'd be curious about your performance tests of GT.M vs. YottaDB if you'd be willing to try both. GT.M requires a thin M shim to access data from node.js or any non-M language, whereas YottaDB exposes a direct, C compatible, API. David Wicksell can confirm, but current versions of NodeM use the C API to access data. The difference is transparent to the node.js code, and of course you can call an M entryref with both. Thank you.

Regards
– Bhaskar

rtweed

unread,
Jun 15, 2020, 11:21:32 AM6/15/20
to Hardhats
Sounds pretty similar to one of my early Node.js interfaces that I worked on back in 2011:


I'd previously (back in 2009) created 2 earlier Node.js clients (mdbm and node-mwire) which took different approaches again.

From experience I can tell you that none of these approaches come even close to the performance and scalability of NodeM / cache.node and now mg-dbx, particularly, as Bhaskar says, if you use YottaDB via its C interface. With mg-dbx (which has resolved some of the V8 API bottlenecks), you're talking near native M performance when accessing the YottaDB database.





Ben Irwin

unread,
Jun 15, 2020, 11:22:25 AM6/15/20
to Hardhats
Bhaskar,

The following numbers are not very meaningful by themselves, there is no comparison yet.  I am calling GT.m in direct mode, not using NodeM.  David and I have talked about using NodeM.  I will consider taking that path in my learning experience.

The testing setup is a little unusual.  This testing is being done on a Mac Book Pro with Parallels.  There is a Windows 10 Pro emulation and includes Intersystems Cache.  This is where the time testing (client) was performed.  There is also a Fedora 32 emulation and includes GT.m and node.js.  This is where the service (server) is running.

I am seeing results in the 16ms range.  This testing method between client and server on the same CPU and wouldn't include network traffic.

Cache Object Script testing code:

TEST
 Quit
 ;
TIMER
 Set httprequest=##class(%Net.HttpRequest).%New()
 Set httprequest.Server="linux.local"
 Set httprequest.Port=8080
 ;
 Set t1=$ZTIMESTAMP
 Do httprequest.Get("/test")
 Set t2=$ZTIMESTAMP
 Do httprequest.Get("/test/param1")
 Set t3=$ZTIMESTAMP
 Do httprequest.Get("/test/param1/param2")
 Set t4=$ZTIMESTAMP
 ;
 Set TMA=$Piece(t2,",",2),TMB=$Piece(t1,",",2) Write "t2-t1: "_(TMA-TMB),!
 Set TMA=$Piece(t3,",",2),TMB=$Piece(t2,",",2) Write "t3-t2: "_(TMA-TMB),!
 Set TMA=$Piece(t4,",",2),TMB=$Piece(t3,",",2) Write "t4-t3: "_(TMA-TMB),!
 Set TMA=$Piece(t4,",",2),TMB=$Piece(t1,",",2) Write "t4-t1: "_(TMA-TMB),!
 ;
 Quit


Cache Object Code test response:

VINFO>D TIMER^TEST
t2-t1: .015
t3-t2: .016
t4-t3: .016
t4-t1: .047

K.S. Bhaskar

unread,
Jun 15, 2020, 5:41:26 PM6/15/20
to Hardhats
Ben –

If the client and server are running in the same OS image and communicating over TCP, there is no network latency, but there is latency from the network software stack.

Regards
– Bhaskar

Ben Irwin

unread,
Jun 15, 2020, 5:50:55 PM6/15/20
to Hardhats
I am not sure of the terminology, but they are running on different OS Images (Windows 10 Pro, Client) and (Fedora 32, Server), but on the same Mac Book Pro.

rtweed

unread,
Jun 17, 2020, 12:53:01 PM6/17/20
to Hardhats
Ben
If you want to do all your API (or interactive app back-end) coding in M, you can still use QEWD, which will look after all the many web-related things, security management, session management etc that you'll need to implement regardless.

What I'd recommend is you first check out: https://github.com/robtweed/qewd-baseline

This includes detailed tutorials on how to create both REST and interactive applications

Within a back-end handler module you can hand off all the logic to a Mumps extrinsic function of your choice, so, for example, your QEWD REST API handler modules could become stubs like this:

module.exports = function(args, finished) {

  let result = this.documentStore.fn('sum^math', args.x, args.y);

  finished({result: result});

};


So in the example above, all the logic is in M code inside sum^math - QEWD is doing the equivalent of  set result=$$sum^math(x,y) 


There's about 11 man-years of Node/M integration work and experience in QEWD, and it's been hammered by lots of people doing all sorts of different things, so it's tried and tested and solid.  Seems a shame not to take advantage of that....


Rob



Ben Irwin

unread,
Jun 17, 2020, 3:04:03 PM6/17/20
to Hardhats
Thanks Rob.
Reply all
Reply to author
Forward
0 new messages