Skip to content

Commit

Permalink
Avoid silently swallowing connection errors
Browse files Browse the repository at this point in the history
When a connection error takes place, the test setup would silently
swallow it (missing callback for `connection.connect()`)

Rewrite the whole thing so that it's easier to follow, to make sure
it awaits the promises, and to use a type interface that aliases
over `mysql` and `mysql2` instead of `any`.
  • Loading branch information
unflxw committed May 6, 2024
1 parent 3868536 commit 496195f
Showing 1 changed file with 65 additions and 18 deletions.
83 changes: 65 additions & 18 deletions test/koa-mysql/app/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Koa from "koa"
import Router from "@koa/router"
import bodyParser from "koa-bodyparser"
import mysql, { Connection } from "mysql"
import mysql from "mysql"
import mysql2 from "mysql2"

const mysqlConfig = {
Expand All @@ -11,6 +11,68 @@ const mysqlConfig = {
database: process.env.MYSQL_DATABASE
}

type MaybeMysqlError = mysql.MysqlError | mysql2.QueryError | null | undefined

interface MysqlConnection {
connect(callback: (err: MaybeMysqlError) => void): void
query(
sql: string,
callback: (err: MaybeMysqlError, rows: any, fields: any) => void
): void
end(callback: (err: MaybeMysqlError) => void): void
}

function connectionPromise(mysqlClient: MysqlModule): Promise<MysqlConnection> {
return new Promise((resolve, reject) => {
let connection = mysqlClient.createConnection(mysqlConfig)

connection.connect((err: MaybeMysqlError) => {
if (err) reject(err)
resolve(connection)
})
})
}

function dummyQueryPromise(connection: MysqlConnection): Promise<any> {
return new Promise((resolve, reject) => {
connection.query(
"SELECT 1 + 1 AS solution",
(err: MaybeMysqlError, rows: any, _fields: any) => {
if (err) reject(err)
try {
resolve(rows[0].solution)
} catch (err) {
reject(err)
}
}
)
})
}

function endConnectionPromise(connection: MysqlConnection): Promise<void> {
return new Promise<void>((resolve, reject) => {
connection.end((err: MaybeMysqlError) => {
if (err) reject(err)
resolve()
})
})
}

async function dummyQuery(mysqlClient: MysqlModule): Promise<any> {
let connection = await connectionPromise(mysqlClient)
let result = await dummyQueryPromise(connection)
await endConnectionPromise(connection)

return result
}

interface MysqlModule {
createConnection(config: typeof mysqlConfig): MysqlConnection
}

const mysqlModule: MysqlModule = mysql
const mysql2Module: MysqlModule = mysql2

const app = new Koa()
const router = new Router()
const port = process.env.PORT
Expand All @@ -26,32 +88,17 @@ router.get("/error", async (_ctx: any) => {
})

router.get("/mysql-query", async (ctx: any) => {
await dummyQuery(mysql)
await dummyQuery(mysqlModule)

ctx.body = "MySQL query received!"
})

router.get("/mysql2-query", async (ctx: any) => {
await dummyQuery(mysql2)
await dummyQuery(mysql2Module)

ctx.body = "MySQL2 query received!"
})

function dummyQuery(mysqlClient: any) {
let connection: Connection

return new Promise((resolve, reject) => {
connection = mysqlClient.createConnection(mysqlConfig)

connection.connect()

connection.query("SELECT 1 + 1 AS solution", (err, rows, _fields) => {
if (err) reject(err)
resolve(rows[0].solution)
})
}).finally(() => connection.end())
}

app.use(router.routes()).use(router.allowedMethods())

app.listen(port)
Expand Down

0 comments on commit 496195f

Please sign in to comment.