Skip to content

Commit 376ba34

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 376ba34

File tree

1 file changed

+59
-18
lines changed

1 file changed

+59
-18
lines changed

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

Lines changed: 59 additions & 18 deletions
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,62 @@ 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(sql: string, callback: (err: MaybeMysqlError, rows: any, fields: any) => void): void
19+
end(callback: (err: MaybeMysqlError) => void): void
20+
}
21+
22+
function connectionPromise(mysqlClient: MysqlModule): Promise<MysqlConnection> {
23+
return new Promise((resolve, reject) => {
24+
let connection = mysqlClient.createConnection(mysqlConfig)
25+
26+
connection.connect((err: MaybeMysqlError) => {
27+
if (err) reject(err)
28+
resolve(connection)
29+
})
30+
})
31+
}
32+
33+
function dummyQueryPromise(connection: MysqlConnection): Promise<any> {
34+
return new Promise((resolve, reject) => {
35+
connection.query("SELECT 1 + 1 AS solution", (err: MaybeMysqlError, rows: any, _fields: any) => {
36+
if (err) reject(err)
37+
try {
38+
resolve(rows[0].solution)
39+
} catch (err) {
40+
reject(err)
41+
}
42+
})
43+
})
44+
}
45+
46+
function endConnectionPromise(connection: MysqlConnection): Promise<void> {
47+
return new Promise<void>((resolve, reject) => {
48+
connection.end((err: MaybeMysqlError) => {
49+
if (err) reject(err)
50+
resolve()
51+
})
52+
})
53+
}
54+
55+
async function dummyQuery(mysqlClient: MysqlModule): Promise<any> {
56+
let connection = await connectionPromise(mysqlClient)
57+
let result = await dummyQueryPromise(connection)
58+
await endConnectionPromise(connection)
59+
60+
return result
61+
}
62+
63+
interface MysqlModule {
64+
createConnection(config: typeof mysqlConfig): MysqlConnection
65+
}
66+
67+
const mysqlModule: MysqlModule = mysql
68+
const mysql2Module: MysqlModule = mysql2
69+
1470
const app = new Koa()
1571
const router = new Router()
1672
const port = process.env.PORT
@@ -26,32 +82,17 @@ router.get("/error", async (_ctx: any) => {
2682
})
2783

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

3187
ctx.body = "MySQL query received!"
3288
})
3389

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

3793
ctx.body = "MySQL2 query received!"
3894
})
3995

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-
5596
app.use(router.routes()).use(router.allowedMethods())
5697

5798
app.listen(port)

0 commit comments

Comments
 (0)