qlik-oss/enigma.js

Socket closed while trying to openDoc()

Closed this issue · 5 comments

Hello!

Description

I am using enigma to create session(s) in order to update application thumbnails.
I need to update a lot of applications at the same time (from 70 to 250+), so I have a function to create a session, using a JWT token or the session cookie (if created).

let Cookie = null;

const createSession = function(appId) {

    console.log(`1 ** App ${appId} ==> Opening session`);

    const enigmaConfig = {
        schema,
        url: `wss://${wsEnv}/${virtualProxyPrefix}/app/${appId || 'engineData'}`,

        createSocket(url) {

            let headers;

            if (Cookie) {
                headers = { Cookie: Cookie }
            } else {
                headers = { Authorization: config.tokenJWT }
            }

            const sock = new WebSocket(url, {
                headers: headers
                // rejectUnauthorized: false
            });

            sock.addEventListener('upgrade', (data, type, target) => {
                if (Cookie) {
                    console.log(`I already have a cookie : ${Cookie}`);
                } else {
                    console.log(`I need a cookie`);
                  Cookie = data.headers['set-cookie'];
                }
            });

            return sock;
        },
    };

    const session = enigma.create(enigmaConfig);

    // session.on('opened', () => console.log(`The session ${session.id} was created for ${appId}`));
    // session.on('closed', () => console.log(`The session ${session.id} was closed for ${appId}`));
    session.on('notification:OnSessionTimedOut', () => session.close());

    return session;
}

Then, I am using that session to open a document, get its properties and set new properties.
openDoc()
getAppProperties()
setAppProperties()

Here's the function

function updateApp(appId, thumbnailUrl) {

  var currentApp;
  const session = createSession(appId);
  const sessionId = session.id;

  return session.open()
    .then(function(_global) {
        console.log(`2 ** App ${appId} ==> Opening document`)
        return _global.openDoc(appId)
      }
    ).catch(
      err => console.error(err)
    )
}

The thing is, that code is working maybe 5% of the time, as for the other 95%, I am getting the same error.
The error is thrown when it tries to openDoc().

1 ** App 0c5b2599-95b5-43ce-9dbf-4fcdb005c539 ==> Opening session
I already have a cookie : AWSALB=+CNfw/2a4U03FHs88zGGh9KU0n046tD379t0mgIfGoZebcCNKUhLtd3ekV/6QWxYYl9WTFM4ugHJSDZG5oGAimI3HmvXkZQEj4We3Srn/hrGWk9AiHMi0dGkE3TG; Expires=Mon, 21 Sep 2020 14:31:01 GMT; Path=/,AWSALBCORS=+CNfw/2a4U03FHs88zGGh9KU0n046tD379t0mgIfGoZebcCNKUhLtd3ekV/6QWxYYl9WTFM4ugHJSDZG5oGAimI3HmvXkZQEj4We3Srn/hrGWk9AiHMi0dGkE3TG; Expires=Mon, 21 Sep 2020 14:31:01 GMT; Path=/; SameSite=None; Secure
2 ** App 0c5b2599-95b5-43ce-9dbf-4fcdb005c539 ==> Opening document
EnigmaError: Socket closed
    at createEnigmaError (C:\Users\Thomas\Documents\30_nodejs\qlik_api\QlikDevAPIs\node_modules\enigma.js\enigma.js:384:12)
    at RPC.onClose (C:\Users\Thomas\Documents\30_nodejs\qlik_api\QlikDevAPIs\node_modules\enigma.js\enigma.js:1523:44)
    at WebSocket.onClose (C:\Users\Thomas\Documents\30_nodejs\qlik_api\QlikDevAPIs\node_modules\ws\lib\event-target.js:129:16)
    at WebSocket.emit (events.js:210:5)
    at WebSocket.emitClose (C:\Users\Thomas\Documents\30_nodejs\qlik_api\QlikDevAPIs\node_modules\ws\lib\websocket.js:191:10)
    at TLSSocket.socketOnClose (C:\Users\Thomas\Documents\30_nodejs\qlik_api\QlikDevAPIs\node_modules\ws\lib\websocket.js:858:15)
    at TLSSocket.emit (events.js:215:7)
    at net.js:658:12
    at TCP.done (_tls_wrap.js:481:7) {
  code: -1,
  enigmaError: true
}

Environment

Library
[x] Node.js
[ ] Browser
Operating system
[x] Windows
[ ] OSX
[ ] Linux
Qlik Sense
[ ] Desktop
[x] Enterprise

Versions

  • Node.js: 12.13.0
  • Qlik Sense: June 2019 Patch 3
  • Operating system: Windows 10 Professional 1909

Thank you for your help!

If you connect through the Qlik Sense Proxy there is a maximum of 5 concurrent sessions. Best would be to connect directly to the engine using certificates. It would also be recommended to open the apps without data to open each app faster (if not already loaded into the engine memory).
https://qlik.dev/apis/json-rpc/qix/global#%23%2Fentries%2FGlobal%2Fentries%2FOpenDoc >> qNoData

Thank you for your feedback!
When I use the session cookie, I sometimes manage to edit more than 70 apps, so I figured that it was not the problem...
I will look into connecting directly to the engine, and that qNoData parameter.

Not sure how the virtual proxy is configured but looking at the console.log from your example it seems that the cookies have to do with AWS load balancer? If you set the JWT as authentication Bearer you don't need to worry about cookies.

Also if you want to connect through the proxy you could use something like bluebirds concurrency

const enigma = require('enigma.js');
const WebSocket = require('ws');
const Promise = require('bluebird');
const schema = require('enigma.js/schemas/12.20.0.json');

const config = {
  schema,
  url: 'ws://localhost:9076/app/',
  createSocket: (url) => new WebSocket(url),
}

const session = enigma.create(config);

(async () => {
  const global = await session.open();
  const apps = await global.getDocList();
  session.close();

  let infos = await Promise.map(apps, async appElm => {
    return await getDocInfo(appElm.qDocName);
  }, {concurrency: 4}); // Using 4 concurrent sessions to be safe 

  console.log("INFOS:", infos);

})().catch(err => {
  console.error(err);
});

const getDocInfo = async (appName) => {
  let localconfig = { ...config };
  localconfig.url += `${encodeURIComponent(appName)}`

  const localSession = await enigma.create(localconfig)
  const localGlobal = await localSession.open();
  const app = await localGlobal.openDoc(appName);
  const appInfo = await app.getAppProperties();
  localSession.close();

  return appInfo;
}

@ostroluge - were you able to solve your issues? Could we close this issue?

I think that my issue is also network related, so I'm closing this issue until I can dig deeper on what is going on.
Thank you for your help!