Merge pull request #6007 from Budibase/fix/postgres-connection

Postgres connection - fixing sporadic issues
This commit is contained in:
Martin McKeaveney 2022-05-23 08:42:17 +01:00 committed by GitHub
commit e6a28aaeed
5 changed files with 49 additions and 27 deletions

View File

@ -41,8 +41,7 @@
"devDependencies": { "devDependencies": {
"ioredis-mock": "^5.5.5", "ioredis-mock": "^5.5.5",
"jest": "^26.6.3", "jest": "^26.6.3",
"pouchdb-adapter-memory": "^7.2.2", "pouchdb-adapter-memory": "^7.2.2"
"pouchdb-all-dbs": "^1.0.2"
}, },
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc" "gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc"
} }

View File

@ -3,13 +3,13 @@ const env = require("../environment")
let PouchDB let PouchDB
let initialised = false let initialised = false
const dbList = new Set()
const put = const put =
dbPut => dbPut =>
async (doc, options = {}) => { async (doc, options = {}) => {
const response = await dbPut(doc, options)
// TODO: add created / updated // TODO: add created / updated
return response return await dbPut(doc, options)
} }
const checkInitialised = () => { const checkInitialised = () => {
@ -28,6 +28,9 @@ exports.init = opts => {
// in situations that using the function doWithDB does not work // in situations that using the function doWithDB does not work
exports.dangerousGetDB = (dbName, opts) => { exports.dangerousGetDB = (dbName, opts) => {
checkInitialised() checkInitialised()
if (env.isTest()) {
dbList.add(dbName)
}
const db = new PouchDB(dbName, opts) const db = new PouchDB(dbName, opts)
const dbPut = db.put const dbPut = db.put
db.put = put(dbPut) db.put = put(dbPut)
@ -63,6 +66,9 @@ exports.doWithDB = async (dbName, cb, opts) => {
} }
exports.allDbs = () => { exports.allDbs = () => {
checkInitialised() if (!env.isTest()) {
return PouchDB.allDbs() throw new Error("Cannot be used outside test environment.")
}
checkInitialised()
return [...dbList]
} }

View File

@ -92,11 +92,5 @@ exports.getPouch = (opts = {}) => {
PouchDB.plugin(find) PouchDB.plugin(find)
} }
const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS) return PouchDB.defaults(POUCH_DB_DEFAULTS)
if (opts.allDbs) {
const allDbs = require("pouchdb-all-dbs")
allDbs(Pouch)
}
return Pouch
} }

View File

@ -14,7 +14,9 @@ module PgMock {
function Client() {} function Client() {}
Client.prototype.query = query Client.prototype.query = query
Client.prototype.end = jest.fn() Client.prototype.end = jest.fn(cb => {
if (cb) cb()
})
Client.prototype.connect = jest.fn() Client.prototype.connect = jest.fn()
Client.prototype.release = jest.fn() Client.prototype.release = jest.fn()

View File

@ -136,7 +136,7 @@ module PostgresModule {
: undefined, : undefined,
} }
this.client = new Client(newConfig) this.client = new Client(newConfig)
this.setSchema() this.open = false
} }
getBindingIdentifier(): string { getBindingIdentifier(): string {
@ -147,7 +147,34 @@ module PostgresModule {
return parts.join(" || ") return parts.join(" || ")
} }
async openConnection() {
await this.client.connect()
if (!this.config.schema) {
this.config.schema = "public"
}
this.client.query(`SET search_path TO ${this.config.schema}`)
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'`
this.open = true
}
closeConnection() {
const pg = this
return new Promise<void>((resolve, reject) => {
this.client.end((err: any) => {
pg.open = false
if (err) {
reject(err)
} else {
resolve()
}
})
})
}
async internalQuery(query: SqlQuery, close: boolean = true) { async internalQuery(query: SqlQuery, close: boolean = true) {
if (!this.open) {
await this.openConnection()
}
const client = this.client const client = this.client
this.index = 1 this.index = 1
// need to handle a specific issue with json data types in postgres, // need to handle a specific issue with json data types in postgres,
@ -164,21 +191,14 @@ module PostgresModule {
try { try {
return await client.query(query.sql, query.bindings || []) return await client.query(query.sql, query.bindings || [])
} catch (err) { } catch (err) {
await this.client.end() await this.closeConnection()
// @ts-ignore // @ts-ignore
throw new Error(err) throw new Error(err)
} finally { } finally {
if (close) await this.client.end() if (close) {
await this.closeConnection()
} }
} }
async setSchema() {
await this.client.connect()
if (!this.config.schema) {
this.config.schema = "public"
}
this.client.query(`SET search_path TO ${this.config.schema}`)
this.COLUMNS_SQL = `select * from information_schema.columns where table_schema = '${this.config.schema}'`
} }
/** /**
@ -188,6 +208,7 @@ module PostgresModule {
*/ */
async buildSchema(datasourceId: string, entities: Record<string, Table>) { async buildSchema(datasourceId: string, entities: Record<string, Table>) {
let tableKeys: { [key: string]: string[] } = {} let tableKeys: { [key: string]: string[] } = {}
await this.openConnection()
try { try {
const primaryKeysResponse = await this.client.query( const primaryKeysResponse = await this.client.query(
this.PRIMARY_KEYS_SQL this.PRIMARY_KEYS_SQL
@ -251,7 +272,7 @@ module PostgresModule {
// @ts-ignore // @ts-ignore
throw new Error(err) throw new Error(err)
} finally { } finally {
await this.client.end() await this.closeConnection()
} }
} }
@ -283,7 +304,7 @@ module PostgresModule {
for (let query of input) { for (let query of input) {
responses.push(await this.internalQuery(query, false)) responses.push(await this.internalQuery(query, false))
} }
await this.client.end() await this.closeConnection()
return responses return responses
} else { } else {
const response = await this.internalQuery(input) const response = await this.internalQuery(input)