Get app reload progress (enigma.js mixin)

Mixin to simplify working with app reload progress and progress messages parsing and format

Get app reload progress (enigma.js mixin)
Photo by Sandy Millar / Unsplash

When I was writing the code for qlBuilder reload command I knew I'll have to come back to it, at some point, and refactor the part that is displaying the reload progress. The plan was to separate this functionality as a separate module or even a package so it can be used elsewhere as well.

And that time has finally came. But instead of a separate package this functionality is now part of enigma-mixin package.

The usage of mGetReloadProgress mixin functionality is a bit niche but it can be used to get the reload progress while reloading an app via enigma.js (same as what Qlik is displaying when reloading an app).

With vanilla enigma.js we have to use GetProgress() API method. But working with it can be a bit tricky. Or at least not trivial.

The main difference between this and the majority of the other API methods is that reloading an app is a long running process and we'll have to call GetProgress() periodically (every X ms) while the app is reloading in order to get the current progress.

The principle here is to not await for the DoReload() (or DoReloadEx()) method but to wrap it in a Promise and inside it to start the reload. After the reload promise is started we'll start pooling every X ms to get the reload progress. Once the doReload() is complete we'll resolve the main promise and return the doReload() response.

const doc = await global.openDoc("some-app-id");

const reloadApp = await new Promise(function (resolve, reject) {
    // start the app reload
    doc.doReload().then((r) => {
        // once the app is reloaded resolve the main promise
        resolve(r);
    });

    // while the app is reloading get the reload progress
    // every 200ms and do something with the response data
    setInterval(function () {
        global.getProgress().then(function (msg) {
            //do something with the message here
        })
    }, 200)

});

// continue here after the app reload is complete

Example of how to use getProgress()

The above snippet gives us an idea how to work with getProgress() method. The next (main?) issue will be to parse the response data of getProgress(). And that can also be challenging due to the nature of the messages/progress.

As you can see getting the reload progress is not as simple as it sounds.

To simplify the process of getting the reload progress I've prepared an enigma.js mixin. More about mixin can be found here and here

By "simplify" I mean that you won't have to deal with getProgress() response data and the hassle that this can bring. I can talk a bit more about the response structure but that can be ... boring 😄(Reach out if you want to know more)

The pseudo code below demonstrates how to import and use the mixin into enigma.js session and how to use it:

import { globalMixin } from "enigma-mixin";

const session = enigma.create({
  schema,
  mixins: globalMixin,
  url: `ws://my-qlik-sense/app/engineData`,
  createSocket: (url) => new WebSocket(url),
});

// open the web socket connection
const global = await session.open();
// open the required app
const doc = await global.openDoc("some-app-id");

// init the get progress mixin
const reloadProgress = global.mGetReloadProgress();

// once the mixin is initialized we can
// prepare the emitter
reloadProgress.emitter.on("progress", (msg) => {
    // here we will receive the reload messages
    console.log(msg);
});

const reloadApp = await new Promise(function (resolve, reject) {
    // or doc.doReloadEx
    doc.doReload().then((r) => {
        // give it another few ms to make sure we have all the messages
        setTimeout(function () {
            // stop the mixin from pooling for new messages.
            // The app reload is already complete at this point
            reloadProgress.stop();
            // resolve the main promise
            resolve(r);
        }, 300);
    });

    // once the reload is started we'll start the pooling
    reloadProgress.start();
});

Pseudo code of how to use mGetReloadProgress mixin

The parsed and formatted reload messages will be available inside the reloadProgress.emitter.on("progress")... function. At the end the messages here will (should) be identical to what is displayed in Qlik.

Qlik (left) and mixin (right) reload results

Follow the link below for the source code and more details about this specific mixin or if you want to know more about the other available mixins. The mGetReloadProgress mixin have a few (optional) parameters that can be set. Like how often to pool for progress and to include/exclude all transient messages.

GitHub - countnazgul/enigma-mixin: Set of custom enigma.js mixins
Set of custom enigma.js mixins. Contribute to countnazgul/enigma-mixin development by creating an account on GitHub.

P.S. The same setup can be used with doSave() method as well. Although it seems that Qlik is not sending any data in the response. Not sure if this is helpful in some way ... just saying 😉

Stefan