Skip to content

feat: Add DataQueue class #151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletions lib/DataQueue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
const { ProgramCall } = require('./ProgramCall');
const { CommandCall } = require('./CommandCall');
const { xmlToJson } = require('./utils');

// QRCVDTAQ Parameters
const QRCVDTAQParameters = {
DataQueueName: { io: 'in', type: '10A' },
LibraryName: { io: 'in', type: '10A' },
LengthOfData: { io: 'in', type: '5p0' },
Data: { io: 'out', type: '10A' },
WaitTime: { io: 'in', type: '5p0' }
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interested in what others think about pulling Parameter information out into a structure like this. Might work a little better after the this PR drops: #139


class DataQueue {
/**
* @description Creates a new DataQueue object
* @constructor
* @param {object} connection
* @param {string} name
* @param {string} library
*/
constructor(connection, name, library = '') {
this.connection = connection;

if (name.length > 10) {
throw Error("DataQueue name must be 10 or fewer characters long.");
}

if (library.length > 10) {
throw Error("DataQueue library must be 10 of fewer characers long.");
}

this.name = name;
this.library = library ? library : '*CURLIB';
this.qualifiedName = this.name.padEnd(10, ' ') + this.library.padEnd(10, ' ');
this.maxLength = undefined;
}

//////////////////////////////////////////////////////////////////////////////
// Create Data Queue (CLDTAQ) CL Command
//////////////////////////////////////////////////////////////////////////////
/**
* @description Creates a Data Queue on the system of the connection passed in
* the constructor.
* @constructor
* @param {number} maxLength
* @param {function} callback
*/
create(maxLength, callback) {
console.log(CommandCall.CommandCall);
this.maxLength = maxLength;
const commandConfig = {
type: 'cl',
command: `CRTDTAQ DTAQ(${this.library ? `${this.library}/` : ''}${this.name}) MAXLEN(${this.maxLength})`
}

this.connection.add(new CommandCall(commandConfig));
this.connection.run((error, xmlOutput) => {
if (error) {
return callback(error);
}

const result = xmlToJson(xmlOutput);
callback(null, result);
});
}

//////////////////////////////////////////////////////////////////////////////
// Delete Data Queue (DLTDTAQ) CL Command
//////////////////////////////////////////////////////////////////////////////
delete(callback) {
const commandConfig = {
type: 'cl',
command: `DLTDTAQ DTAQ(${this.library ? `${this.library}/`: ''}${this.name})`
}

this.connection.add(new CommandCall(commandConfig));
this.connection.run((error, xmlOutput) => {
if (error) {
return callback(error);
}

const result = xmlToJson(xmlOutput);
callback(null, result);
});
}

//////////////////////////////////////////////////////////////////////////////
// Receive Data Queue (QRCVDTAQ) API
//////////////////////////////////////////////////////////////////////////////

async receive(wait, length, callback) {
if (typeof wait === 'function') {
callback = wait;
wait = 0;
}

if (length == undefined) {
if (this.maxLength == undefined) {
const description = await this._getDataQueueDescription();
this.maxLength = description[0].data[2].value;
}

length = this.maxLength;
}

const program = new ProgramCall('QRCVDTAQ', { lib: 'QSYS' });

program.addParam(this.name, QRCVDTAQParameters.DataQueueName.type, { io: QRCVDTAQParameters.DataQueueName.io });
program.addParam(this.library, QRCVDTAQParameters.LibraryName.type, { io: QRCVDTAQParameters.LibraryName.io });
program.addParam(length, QRCVDTAQParameters.LengthOfData.type, { io: QRCVDTAQParameters.LengthOfData.io });
program.addParam('', `${this.maxLength}A`, { io: QRCVDTAQParameters.Data.io });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about how to do this for "structures" (the array) to get the len and then using setlen, but can I do the same for single values? And should I here, with the LengthOfData parameter?

program.addParam(wait, QRCVDTAQParameters.WaitTime.type, { io: QRCVDTAQParameters.WaitTime.io });

this.connection.add(program)
this.connection.run((error, xmlOutput) => {
if (error) {
return callback(error, null);
}
const result = xmlToJson(xmlOutput);
const data = result[0].data[0].value;
return callback(null, data);
});
}

// alias for receive, as the API is "RCV", but jt400 uses the term "read"
async read(wait, callback) {
return this.receive(wait, callback);
}

//////////////////////////////////////////////////////////////////////////////
// Send Data Queue (QSNDDTAQ) API
//////////////////////////////////////////////////////////////////////////////

async send(data, callback) {
const program = new ProgramCall('QSNDDTAQ', { lib: 'QSYS' });
program.addParam(this.name, '10A'); // Data queue name
program.addParam(this.library, '10A'); // Library name
program.addParam(data.length, '5p0'); // Length of data
program.addParam(data, `${data.length}A`); // Data

this.connection.add(program)
this.connection.run((error, xmlOutput) => {
if (error) {
return callback(error, null);
}
const result = xmlToJson(xmlOutput);
return callback(null, result);
});
}

async write(data, callback) {
return this.write(data, callback);
}

//////////////////////////////////////////////////////////////////////////////
// Clear Data Queue (QCLRDTAQ) API
//////////////////////////////////////////////////////////////////////////////

async clear() {
const program = new ProgramCall('QCLRDTAQ', { lib: 'QSYS' });
program.addParam(this.name, '10A'); // Data queue name
program.addParam(this.library, '10A'); // Library name

this.connection.add(program)
this.connection.run((error, xmlOutput) => {
if (error) {
return callback(error, null);
}
const result = xmlToJson(xmlOutput);
return callback(null, result);
});
}

//////////////////////////////////////////////////////////////////////////////
// "Private" Functions
//////////////////////////////////////////////////////////////////////////////


async _getDataQueueDescription(callback) {
const program = new ProgramCall('QMHQRDQD', { lib: 'QSYS' });

const receiverVariable = [
[0, '10i0'],
[0, '10i0'],
[0, '10i0']
];

program.addParam(receiverVariable, { io: 'out', len: 'varLen'}); // Receiver variable
program.addParam(0, '10i0', { setlen: 'varLen'}); // Length of receiver variable
program.addParam('RDQD0100', '8A'); // Format name
program.addParam(this.qualifiedName, '20A'); // Qualified data queue name

this.connection.add(program)
this.connection.run((error, xmlOutput) => {
if (error) {
return callback(error, null);
}

const result = xmlToJson(xmlOutput);
this.maxLength = result[0].data[2].value
return callback(null, result);
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea here is:

If we create a DataQueue using this API, we know what the max length is. But if we are consuming a DataQueue created elsewhere, we don't know the max size. So when we need to get the length the first time we call an API that requires us to specify the length of the receiver data

}
}

module.exports.DataQueue = DataQueue;
2 changes: 2 additions & 0 deletions lib/itoolkit.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const { CommandCall } = require('./CommandCall');
const { Connection } = require('./Connection');
const { Toolkit } = require('./Toolkit');
const { xmlToJson } = require('./utils');
const { DataQueue } = require('./DataQueue');

const {
iPgm,
Expand All @@ -49,6 +50,7 @@ module.exports = {
Connection,
Toolkit,
xmlToJson,
DataQueue,
// deprecated exports below, replaced by functionality above
iCmd,
iConn,
Expand Down