Skip to content

Commit ef792a5

Browse files
committed
Avoid silently swallowing connection errors
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`.
1 parent 3868536 commit ef792a5

File tree

1 file changed

+65
-18
lines changed

1 file changed

+65
-18
lines changed

test/koa-mysql/app/src/app.ts

+65-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Koa from "koa"
22
import Router from "@koa/router"
33
import bodyParser from "koa-bodyparser"
4-
import mysql, { Connection } from "mysql"
4+
import mysql from "mysql"
55
import mysql2 from "mysql2"
66

77
const mysqlConfig = {
@@ -11,6 +11,68 @@ const mysqlConfig = {
1111
database: process.env.MYSQL_DATABASE
1212
}
1313

14+
type MaybeMysqlError = mysql.MysqlError | mysql2.QueryError | null | undefined
15+
16+
interface MysqlConnection {
17+
connect(callback: (err: MaybeMysqlError) => void): void
18+
query(
19+
sql: string,
20+
callback: (err: MaybeMysqlError, rows: any, fields: any) => void
21+
): void
22+
end(callback: (err: MaybeMysqlError) => void): void
23+
}
24+
25+
function connectionPromise(mysqlClient: MysqlModule): Promise<MysqlConnection> {
26+
return new Promise((resolve, reject) => {
27+
const connection = mysqlClient.createConnection(mysqlConfig)
28+
29+
connection.connect((err: MaybeMysqlError) => {
30+
if (err) reject(err)
31+
resolve(connection)
32+
})
33+
})
34+
}
35+
36+
function dummyQueryPromise(connection: MysqlConnection): Promise<any> {
37+
return new Promise((resolve, reject) => {
38+
connection.query(
39+
"SELECT 1 + 1 AS solution",
40+
(err: MaybeMysqlError, rows: any, _fields: any) => {
41+
if (err) reject(err)
42+
try {
43+
resolve(rows[0].solution)
44+
} catch (err) {
45+
reject(err)
46+
}
47+
}
48+
)
49+
})
50+
}
51+
52+
function endConnectionPromise(connection: MysqlConnection): Promise<void> {
53+
return new Promise<void>((resolve, reject) => {
54+
connection.end((err: MaybeMysqlError) => {
55+
if (err) reject(err)
56+
resolve()
57+
})
58+
})
59+
}
60+
61+
async function dummyQuery(mysqlClient: MysqlModule): Promise<any> {
62+
const connection = await connectionPromise(mysqlClient)
63+
const result = await dummyQueryPromise(connection)
64+
await endConnectionPromise(connection)
65+
66+
return result
67+
}
68+
69+
interface MysqlModule {
70+
createConnection(config: typeof mysqlConfig): MysqlConnection
71+
}
72+
73+
const mysqlModule: MysqlModule = mysql
74+
const mysql2Module: MysqlModule = mysql2
75+
1476
const app = new Koa()
1577
const router = new Router()
1678
const port = process.env.PORT
@@ -26,32 +88,17 @@ router.get("/error", async (_ctx: any) => {
2688
})
2789

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

3193
ctx.body = "MySQL query received!"
3294
})
3395

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

3799
ctx.body = "MySQL2 query received!"
38100
})
39101

40-
function dummyQuery(mysqlClient: any) {
41-
let connection: Connection
42-
43-
return new Promise((resolve, reject) => {
44-
connection = mysqlClient.createConnection(mysqlConfig)
45-
46-
connection.connect()
47-
48-
connection.query("SELECT 1 + 1 AS solution", (err, rows, _fields) => {
49-
if (err) reject(err)
50-
resolve(rows[0].solution)
51-
})
52-
}).finally(() => connection.end())
53-
}
54-
55102
app.use(router.routes()).use(router.allowedMethods())
56103

57104
app.listen(port)

0 commit comments

Comments
 (0)