Last active
December 19, 2021 08:50
-
-
Save samin/190f6058f5fe90ded5318db21ce1653c to your computer and use it in GitHub Desktop.
RDS Data API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const RDSDataAPIClient = require('RDSDataAPIClient'); | |
const knex = require('knex')({ | |
client: RDSDataAPIClient, | |
connection: { | |
secretArn, | |
resourceArn, | |
database | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
@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.
Just found something to take in consideration: limits in packet size and response size:
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
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.