QLDB Node Driver v1.0.0
- 4 minutes read - 760 wordsAmazon QLDB Driver for NodeJS
On Friday 3rd April, the Amazon QLDB team announced release v1.0.0 of the Amazon QLDB Driver for NodeJS. I was excited to give this a try, and see how it compared to the preview version. This is a brief summary of my initial findings.
Setting Up
The driver has a number of peer dependencies:
- aws-sdk (AWS SDK for JavaScript)
- ion-js (Amazon ION data format)
- jsbi (pure JavaScript implementation of BigInt, which is new for this release)
The ion-js
library has jumped to version 4.0.0, and there is a new peer dependency on jsbi
, a pure-JavaScript implementation of the official ECMAScript BigInt proposal.
Connecting to a ledger
Using the driver to connect to the ledger is carried out in the same way.
Creating a table
The first issue came when looking to create a table as part of a custom resource. This was using the executeInline
function on the TransactionExecutor
and resulted in the following error message:
INFO error: TypeError: txn.executeInline is not a function
In the new driver, the executeInline
function has been renamed to simply execute
. This just meant updating the createTable
function I used accordingly.
async function createTable(txn, tableName){
const statement = `CREATE TABLE ${tableName}`;
return await txn.execute(statement).then((result) => {
Log.debug(`Successfully created table ${tableName}.`);
return result.getResultList().length;
});
}
Inserting data
A basic function that inserted data using the previous driver is shown below:
async function insertNewVehicleRecord(txn, documents) {
Log.debug("In the insertNewVehicleRecord function");
const statement = `INSERT INTO Vehicle ?`;
const ionWriter = createQldbWriter();
writeValueAsIon(documents, ionWriter);
return await txn.executeInline(statement, [ionWriter]);
}
Previously, when passing a parameter to a parametised query, you had to first convert the native data type into a QLDBWriter
type. This involved creating a QLDBWriter
object, and then writing the converted value to it. This was done in the help function called writeValueAsIon()
which provided this functionality e.g.
switch (typeof value) {
case "string":
ionWriter.writeString(value);
break;
case "boolean":
ionWriter.writeBoolean(value);
break;
case "number":
ionWriter.writeInt(value);
break;
...
Now, with the updated driver, you can simply pass the native data type as a parameter without having to convert to an Ion Value type, which is so much simpler. The original function can be now be re-written as follows:
async function insertNewVehicleRecord(txn, documents) {
Log.debug("In the insertNewVehicleRecord function");
const statement = `INSERT INTO Vehicle ?`;
return await txn.execute(statement, documents);
}
Selecting data
One of the biggest challenges I found with the previous version of the driver was retrieving a record and then parsing it into a JSON object. With the previous driver, it was relatively straight forward to capture the data returned in ION format. This was done by creating a new ION Writer, and using this to write all the values from the Reader into a UTF-8 encoded buffer, and writing this out as shown below:
const result = await getVehicleByVRN(txn, vrn);
const resultList = result.getResultList();
const writer = makeTextWriter();
resultList.forEach((reader) => {
writer.writeValues(reader);
});
Log.debug(decodeUtf8(writer.getBytes()));
This produced the following output in my simple example:
"{VRN:\"ABC123\",Make:\"Ford\",Model:\"Fiesta\",Colour:\"Red\"}"
The problem with this is that this ION format is not valid JSON. If you attempt to JSON.parse()
this value, you get the following exception:
SyntaxError: Unexpected token V in JSON at position 1
This left me with no option in Nodejs but to navigate through the reader by using methods like stepIn()
, stepOut()
, next()
and so on, to obtain the fields from the result. An example of this is shown below. This involved stepping into the list, looping through, and extracting all the field names and values, which was hard going and cumbersome:
let ionReader = makeReader(decodeUtf8(writer.getBytes()));
ionReader.next();
ionReader.stepIn(); // Step into the list.
...
while (ionReader.next() != null) {
stringBuilder += `'${ionReader.fieldName()}':'${ionReader.stringValue()}'`;
...
This is made much simpler with the new driver, which is more intuitive and gives a far nicer experience. It uses the recently released Ion JS DOM API to return Ion DOM values instead of returning IonReader
. The DOM values are extensions of the Javascript native data types, and so all the methods I needed work out of the box, which includes JSON.stringify()
and JSON.parse()
. The code snippet below was all I needed to populate a JSON object that could be returned to a consumer:
const result = await getVehicleByVRN(txn, vrn);
const resultList = result.getResultList();
Log.debug(JSON.stringify(resultList[0]));
Overview
The new Amazon QLDB Driver for Nodejs is a huge step forward from the previous driver. I’ve been able to remove a significant amount of code, including the nightmare that was stepping into an ION reader to process the response from executing PartiQL statements. This has instantly made the code much simpler and easier to read.