Rob Tweed · Jul 20, 2017 go to post

By the way, using cache.node as the interface gives the benefit of a high-performance in-process connection to Cache from JavaScript - significantly faster than using a networked connection, as it connects at a very low-level directly into the core global engine via Cache's C-based call-in interface.  

There's still currently a limitation however, due to a V8 API bottleneck, described here:

https://bugs.chromium.org/p/v8/issues/detail?id=5144#c1

My simple experiments comparing Global access performance via native COS versus cache.node and JavaScript show that connecting from Node.js via cache.node provides only about 10% of native COS performance - so a 90% performance reduction, apparently all due to this V8 bottleneck!  Nevertheless, my comparisons of MongoDB performance versus using Globals as a document database show that MongoDB is only relatively slightly faster.

If this V8 API problem was fixed, then access to Cache via cache.node would be as fast as using native COS.  The outcome, if my experimentation has been correct, would be that MongoDB would be significantly out-performed by Cache as a document database.  Additionally, my prediction would be that your MongoDB emulation could also outperform the real thing too - a rather interesting and somewhat startling result if true.

I would love to see this V8 bottleneck resolved.  I wonder if there's anyone in this community that could take on that challenge, or perhaps knows someone with the skills to take it on?  I think a lot of people would sit up and take notice of what could become the fastest Node.js-connected NoSQL database on the planet.

Rob

Rob Tweed · Jul 19, 2017 go to post

> The Caché Node.js driver could not access Caché classes, but could make program calls from Caché. This fact resulted in the

>creation of a small tool - a kind of bridge between the driver and Caché classes.

This is incorrect - cache.node can access Cache Objects. See:

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…

Also take a look at this:

https://github.com/chrisemunt/mongo-dbx

as an alternative MongoDB interface

Rob Tweed · Jul 11, 2017 go to post

You miss the point - Node.js / JavaScript is now one of the most used back-ends / languages.  By comparison, COS is almost unknown in the IT mainstream.  Sure, you can do everything in COS, but to do so, you need to learn COS.  If you have to learn COS to use Cache, most people in IT won't use it as the back-end to web applications.

Write your apps the way Ward suggests, and  you open up Cache to a massively bigger audience, and you can also recruit JavaScript guys to do the back-end development, without them having to learn COS, but they get all the benefits of the database.

Regarding performance, see my last comment for this article:

https://community.intersystems.com/post/building-qewd-nodejs-cache-rest…

and see for yourself - look at the browser console network logs and look at the X-ResponseTime response header values to see the back-end response time using Node.js + Cache - here's the demo link:

http://34.201.135.122:8080/

Suggestion - put together a COS/CSP version of the RealWorld Conduit back-end and see how it performs by comparison, so you get an apples v apples comparison

Rob Tweed · Jul 11, 2017 go to post

> So far NodeJS is only used as a general dev environment and build pipeline manager.

This is just not true

Rob Tweed · Jul 8, 2017 go to post

Representing XML and JSON in Global Storage is an interesting area.

In the case of XML, things are a little more complex than described in your article, since there's something of an ambiguity between information stored in the text value of an element and an attribute of an element.  For this reason, the better representation is to model the XML DOM in Global Storage nodes.  You'll find a pretty thorough (and free, Open Source) implementation here:

https://github.com/robtweed/EWD

This article provides more information:

https://groups.google.com/forum/#!searchin/enterprise-web-developer-com…

Once in DOM format you can apply cool stuff such as XPath querying.  See:

https://groups.google.com/forum/#!searchin/enterprise-web-developer-com…

The DOM is essentially modelled in Global Storage as a graph.  DOM programming is extremely powerful, allowing all sorts of complex things to be performed very efficiently and simply.

JSON is much simpler, being a pure hierarchy.  The only ambiguity with Global Storage is that JSON only allows leaf nodes to hold data - intermediate nodes cannot.  However, Global nodes can be intermediate nodes AND store data.  So whilst all JSON trees can be represented as a Global tree, not all Global trees can be represented as JSON.

The Node.js-based QEWD.js framework uses Global Storage as an embedded database to provide Session storage, persistent JavaScript Objects and a fine-grained Document Database.  To see how this is done, see the training course slide decks:

http://ec2.mgateway.com/ewd/ws/training.html

..specifically parts 17 - 27

Keep up the great work on this series of articles!

Rob

Rob Tweed · Jun 1, 2017 go to post

Perhaps someone from InterSystems should respond with respect to Sean's views on cache.node?

Rob Tweed · Jun 1, 2017 go to post

I don't know why you don't use the cache.node interface?   It will support in excess of 100k global sets/second per connection.  Is there something you believe it doesn't do that you need?

Rob Tweed · May 31, 2017 go to post

Very good article - good to see Global Storage being discussed.  Thanks for the compliments!  We need this kind of discussion to be promulgated out to a wider audience, not just preaching here to the (largely) already converted.  

I despair when I go to technical conferences where not one single attendee I speak to has heard of Cache or Global Storage.  Yet it's a database technology and architecture that is ideally suited to todays requirements (and particularly suited to the burgeoning JavaScript world), and is crying out to be more widely known about.  I do my best to get new interest in the mainstream, but feel I'm something of a lone voice in the wilderness.

The other thing I'd love to see is to have at my disposal within Node.js a similar level of performance as the article has described when using native Cache Objectscript.  It turns out there's just one Google V8 bottleneck in the way - if that could be sorted out, the idea of having a database in Node.js that could persist JSON data at speeds in excess of 1 million name/value pairs per second would blow every other database clean out of the water.  I would LOVE to see this rectified , and if fixed, it could create a huge wave of interest (people at those conferences I go to might actually want to find out about it!)

Here's the issue:

https://bugs.chromium.org/p/v8/issues/detail?id=5144#c1

Anyway, looking forward to part 2 of the article.

Someone should do a talk at the Developers Conference.... ??

Rob Tweed · May 27, 2017 go to post

Have you tried some tests just using a simple test harness Node.js file built around cache.node, and building out your example that uses cache.node's invoke_classmethod, extending it step by step until it fails?   

Rob Tweed · May 11, 2017 go to post

I've just pushed out a new set of enhancements to QEWD that are described here:

https://robtweed.wordpress.com/2017/05/11/qewd-now-supports-koa-js-and-…

I've upgraded the Cache-based RealWorld Conduit demo to make use of Koa.js.  As suggested in the article, take a look at the X-ResponseTime response headers in our browser's JavaScript console to get an idea just how fast the combination of QEWD, Koa.js, Node.js + Cache really is.  The URL for the live demo is:

   http://34.201.135.122:8080

Rob

Rob Tweed · May 10, 2017 go to post

Hi David

Glad to hear your success in getting it working for you.

There's a right way and a somewhat dodgy way to do what you want to do.

The right way is to have separate instances of QEWD, each connected to a particular namespace and listening on a different port.  You could probably proxy them via some URL re-writing (eg with nginx at the front-end)

The dodgy way which I think should work is to have a function wrapper around $zu(5) (or equivalent) to change namespace, and make a call to this in each of your back-end handler functions.  If you do this you need to make sure that you switch back to the original namespace before your finished() call and return from your function.  If an unexpected error occurs, you need to realise that your worker process could end up stuck in the wrong namespace.

Your namespace-switching function would need to be callable from all your Cache namespaces - use routine mapping for this.

Doing this namespace switching will be at your own risk - see how it goes

BTW for these type of situations where you want to do the same thing before and after every handler function, you might find the latest feature (beforeHandler and afterHandler) described here very useful:

https://groups.google.com/forum/#!topic/enterprise-web-developer-commun…

Rob

Rob Tweed · May 4, 2017 go to post

I've set up this instance of the Conduit Application:

http://34.201.135.122:8080

It uses: 

- Cache 2015.2, running on Ubuntu  Linux and Node.js v6.10, on an AWS EC2 instance

- QEWD with 2 child processes

- qewd-conduit RealWorld Conduit back-end

- The React/Redux version of the front-end for Conduit, with its data served up via REST calls to the qewd-conduit back-end

Note: no changes were needed for the application to run with Cache.

Rob Tweed · May 2, 2017 go to post

Thanks Ward!

I've now added a "Guided Tour" to the ReadMe of the qewd-conduit Github repo, which people will find helpful as an explanation of how the app works and is put together.

Please use this as a guide to building your own QEWD/Cache applications

Rob Tweed · May 1, 2017 go to post

Yes - qewd-conduit is a pure REST back-end.  As such it has no front-end markup (though it could).  The /api endpoint does not, in itself, have any meaning - it's just the root URL for all the valid Conduit endpoints, eg GET /api/tags

qewd-conduit returns JSON responses, not HTML

Rob Tweed · May 1, 2017 go to post

Yes - there is no actual endpoint at /api, hence the error response.

Try one of the unauthenticated endpoints that is documented in the RealWorld Conduit API document, such as /api/tags and you'll get a proper response

Rob

Rob Tweed · Apr 26, 2017 go to post

Regarding the installation of QEWD, it's worth pointing out that the Github/NPM repository includes an installers folder which contains a number of installer scripts for Linux-based systems. There's even one for QEWD + Linux + Cache, although it shouldn't be run as a script since you will probably already have Cache installed - use it instead as a guide for the commands you need to run in order to install the various bits and pieces.

See https://github.com/robtweed/qewd/tree/master/installers

There's even an installer for the Raspberry Pi, although that can't use Cache (sadly!)

Another alternative is to use the Docker appliance, but it would need to be adapted to work with Cache.  See https://github.com/robtweed/qewd/tree/master/docker

Rob Tweed · Apr 21, 2017 go to post

Chris Munt would be the person to ask, but I'm not aware that the lack of a resolution to the bottleneck issue is anything to with security - more that Google don't "get" the issue and see it as a priority, since it's an unusual requirement.

Anyway cache.node is an official InterSystems interface so why not just use it instead of rolling your own?  Ideally ISC should be pushing Google to fix the bottleneck.

Rob Tweed · Apr 21, 2017 go to post

cache.node will handle in excess of 90,000 global sets/sec in its in-process mode.  If that V8 bottleneck was sorted out, we'd have COS performance for JS accessing a Cache database (ie > 1,000,000 global sets / sec)

With QEWD (actually ewd-qoper8), you find that for simple message handling, optimum throughput is when the number of Node.js processes (master + workers) equals the number of CPU cores.  That's a Node.js context switching issue, nothing to do with Cache.

QEWD allows you to configure cache.node to work in networked mode, in which case you can have Cache running on a separate server to the Node.js machine.  I've not compared performance, but it's a simple QEWD startup-file setting change to switch modes, so easy to compare if you want to give it  a try.

QEWD is very quick and easy to set up on a Windows machine where Cache is already installed.  See:

https://www.slideshare.net/robtweed/installing-configuring-ewdxpress

Rob Tweed · Apr 21, 2017 go to post

Just to clarify - despite the bottleneck I've mentioned, cache.node will be a LOT faster than a TCP-based Node.js interface.  cache.node runs in-process with the Node.js process, and uses the Cache call-in interface.  As a result, QEWD is very fast and my guess is that it should outstrip an equivalent app using CSP.

Also, note that with QEWD, the socket.io connections are between the browsers and the QEWD master process, and NOT the child/worker processes that connect to Cache.  So Cache is decoupled from the web-socket and, indeed the HTTP(S) interfacing.

Rob Tweed · Apr 21, 2017 go to post

See my recent article on QEWD for the rationale behind its architecture:

https://robtweed.wordpress.com/2017/04/18/having-your-node-js-cake-and-…

As to benchmarks, the ewd-qoper8 module comes with a benchmarking app - even on a basic Linux VM setup, I can easily get in excess of 10,000 message round-trips per second.  Of course, once you add QEWD's access to Cache via cache.node, that will drop.  cache.node is a bottle-neck currently, for V8-related reasons described here:

https://groups.google.com/forum/#!searchin/v8-dev/bottleneck%7Csort:dat…

It would be great if Google could fix this as we'd then get native COS performance via JS

As to moving parts, QEWD is entirely Node.js-based, so no extra moving parts other than Node.

Rob Tweed · Apr 21, 2017 go to post

You're probably too far down the line in terms of CSP development, but this kind of multi-lingual capability was something that was available years ago in our (M/Gateway)'s original EWD product which could generate CSP pages as one of its many run-time targets.  In fact, multi-lingual support was there from the beginning as it was developed initially for a customer who needed 6 European language translations of the same CSP application. and needed to minimise the time and effort needed to create the translations (done externally by a third-party service) AND keep them all in sync whilst the application was still in active development and then in ongoing maintenance.

Here's the original documentation for anyone interested:

http://gradvs1.mgateway.com/download/multiLingual.pdf

Although my efforts are now focused on the Node.js/JavaScript based QEWD generation of products, the original EWD is still available - it's actually in production use by Quest Diagnostics as the basis of their Internet-based Care360 application, so it's rock-solid and still fully supported.  For information on EWD, go to www.mgateway.com and click the Legacy link.

Rob

Rob Tweed · Apr 21, 2017 go to post

QEWD (and EWD.js before it) has been using WebSockets for years with Cache at the back-end.  Of course, in this case, WebSocket support is provided by the Node.js socket.io module, so it avoids any COS-related issues.  It works extremely well and is very fast, stable and scalable.  Personally I'd always use WebSockets in preference to Ajax for browser to/from back-end communication.

However, one of the tricks QEWD pulls off is to allow you to transparently switch between Ajax and WebSockets as the transport for browser communication - for you, the developer, there's no difference in how you transfer messages, so you can choose the transport that is right for you via a simple configuration switch.  See:

https://www.slideshare.net/robtweed/ewd-3-training-course-part-14-using…