Skip to content

Instantly share code, notes, and snippets.

@samin
Last active December 19, 2021 08:50
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save samin/190f6058f5fe90ded5318db21ce1653c to your computer and use it in GitHub Desktop.
Save samin/190f6058f5fe90ded5318db21ce1653c to your computer and use it in GitHub Desktop.
RDS Data API
const RDSDataAPIClient = require('RDSDataAPIClient');
const knex = require('knex')({
client: RDSDataAPIClient,
connection: {
secretArn,
resourceArn,
database
},
});
const Bluebird = require('bluebird');
const { isUndefined } = require('lodash');
const Client = require('knex/lib/dialects/mysql');
const Transaction = require('knex/lib/transaction');
const inherits = require('inherits');
const sqlstring = require('sqlstring');
class RDSDataAPITransaction extends Transaction {
commit(conn, value) {
this._completed = true;
return conn
.commitTransaction({
transactionId: conn.__knexTxId,
})
.then(() => this._resolver(value));
}
rollback(conn, err) {
const self = this;
this._completed = true;
return conn
.rollbackTransaction({
transactionId: conn.__knexTxId,
})
.then((status) => {
if (isUndefined(err)) {
if (self.doNotRejectOnRollback) {
self._resolver();
return;
}
err = new Error(`Transaction rejected with non-error: ${err}`);
self._rejecter(err);
return;
}
if (status.transactionStatus === 'Rollback Complete') {
self._rejecter(err);
return;
}
err = new Error(status.transactionStatus);
self._rejecter(err);
});
}
acquireConnection() {
const self = this;
return new Bluebird(((resolve, reject) => {
self.client
.acquireConnection()
.then((cnx) => {
cnx.beginTransaction(self.client.connectionSettings).then((result) => {
cnx.__knexTxId = result.transactionId;
cnx.isTransaction = true;
resolve(cnx);
});
resolve(cnx);
})
.catch(reject);
}));
}
}
function ClientRDSDataAPI(config) {
Client.call(this, config);
}
inherits(ClientRDSDataAPI, Client);
Object.assign(ClientRDSDataAPI.prototype, {
driverName: 'rds-data',
_driver() {
return require('data-api-client');
},
transaction() {
return new RDSDataAPITransaction(this, ...arguments);
},
acquireConnection() {
const connection = this.driver(this.connectionSettings);
return Bluebird.resolve(connection);
},
// Runs the query on the specified connection, providing the bindings
// and any other necessary prep work.
_query(connection, obj) {
if (!obj || typeof obj === 'string') obj = { sql: obj };
return new Bluebird((async (resolver) => {
if (!obj.sql) {
resolver();
return;
}
const result = await connection.query({
sql: sqlstring.format(obj.sql, obj.bindings),
continueAfterTimeout: true,
transactionId: obj.__knexTxId,
});
obj.response = result;
resolver(obj);
}));
},
// Process the response as returned from the query.
processResponse(obj) {
return obj.response.records;
},
});
module.exports = ClientRDSDataAPI;
@cdelgadob
Copy link

Hey! Thanks for this, looks promising.
I was just wondering how to pass the connection options to the driver, which is used when the process connects to the data api from outside.

const dataApiOpts:any = {
    secretArn: process.env.DB_SECRET_ARN,
    resourceArn: process.env.DB_RESOURCE_ARN,
    database: db_schema
  }

  if (process.env.IS_OFFLINE) {
    dataApiOpts.options = {
      endpoint: 'https://rds-data.eu-west-1.amazonaws.com',
      accessKeyId: process.env.ACCESS_KEY_ID,
      secretAccessKey: process.env.SECRET_ACCESS_KEY,
      region: 'eu-west-1'
    }
  }

So here the options property is not allowed, and fails. The same occurs if I try to pass the options properties directly in the dataApiOpts object.

@cdelgadob
Copy link

cdelgadob commented Jul 26, 2019

@samin I forked your gist to allow connections from outside AWS, please take a look.

Maybe it's a bit hacky but I didn't have time to find another way.

@cdelgadob
Copy link

Just found something to take in consideration: limits in packet size and response size:

https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html#data-api.troubleshooting.packet-too-large

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment