Skip to content

Commit a866d16

Browse files
committed
tests: Add tests for client auto-reconnect after connection drop behaviour
1 parent 89fbd77 commit a866d16

1 file changed

Lines changed: 105 additions & 2 deletions

File tree

tests/query_client_test.ts

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import {
1313
assertRejects,
1414
assertThrows,
1515
} from "jsr:@std/assert@1.0.10";
16+
import {
17+
MockError,
18+
stub,
19+
} from "jsr:@std/testing/mock";
1620
import { getMainConfiguration } from "./config.ts";
1721
import type { PoolClient, QueryClient } from "../client.ts";
1822
import type { ClientOptions } from "../connection/connection_params.ts";
@@ -694,9 +698,13 @@ Deno.test(
694698
);
695699

696700
// This test depends on the assumption that all clients will default to
697-
// one reconneciton by default
701+
// one reconnection by default
702+
//
703+
// It also specifically tests the case where the database system sends a
704+
// graceful disconnect, not the case where the database connection is just
705+
// closed due to the database process crashing or being killed.
698706
Deno.test(
699-
"Default reconnection",
707+
"Default reconnection after graceful database connection close",
700708
withClient(async (client) => {
701709
await assertRejects(
702710
() =>
@@ -714,6 +722,66 @@ Deno.test(
714722
}),
715723
);
716724

725+
// This test depends on the assumption that all clients will default to
726+
// one reconnection by default
727+
Deno.test(
728+
"Default reconnection after connection drop",
729+
withClient(async (client) => {
730+
// Test that connection is OK
731+
const { rows: result } = await client.queryObject<{ res: number }>({
732+
text: `SELECT 1`,
733+
fields: ["res"],
734+
});
735+
assertEquals(result[0].res, 1);
736+
737+
// Use mock simulate irrecoverably broken pipe
738+
const connWrite = stub(
739+
WritableStreamDefaultWriter.prototype,
740+
"write",
741+
(_buffer) => {
742+
throw new Deno.errors.BrokenPipe();
743+
}
744+
);
745+
try {
746+
await assertRejects(
747+
() =>
748+
client.queryArray`SELECT 1`,
749+
Deno.errors.BrokenPipe,
750+
);
751+
} finally {
752+
connWrite.restore();
753+
}
754+
755+
// Use mock simulate broken pipe, that can be healed by reconnecting
756+
const connWrite2 = stub(
757+
WritableStreamDefaultWriter.prototype,
758+
"write",
759+
(_buffer) => {
760+
connWrite2.restore();
761+
throw new Deno.errors.BrokenPipe();
762+
}
763+
);
764+
try {
765+
const { rows: result2 } = await client.queryObject<{ res: number }>({
766+
text: `SELECT 1`,
767+
fields: ["res"],
768+
});
769+
assertEquals(result2[0].res, 1);
770+
} finally {
771+
// Restoring must fail here because it already happened
772+
//
773+
// If this fails, it means the Mock was never invoked and the test must be updated!
774+
assertThrows(
775+
() =>
776+
connWrite2.restore(),
777+
MockError,
778+
);
779+
}
780+
781+
assertEquals(client.connected, true);
782+
}),
783+
);
784+
717785
Deno.test(
718786
"Handling of debug notices",
719787
withClient(async (client) => {
@@ -1498,6 +1566,41 @@ Deno.test(
14981566
}),
14991567
);
15001568

1569+
Deno.test(
1570+
"Transaction fails after connection drop",
1571+
withClient(async (client) => {
1572+
const name = "transactionFailsOnConnectionDrop";
1573+
const transaction = client.createTransaction(name);
1574+
1575+
await transaction.begin();
1576+
1577+
// Use mock simulate broken pipe
1578+
const connWrite = stub(
1579+
WritableStreamDefaultWriter.prototype,
1580+
"write",
1581+
(_buffer) => {
1582+
throw new Deno.errors.BrokenPipe();
1583+
}
1584+
);
1585+
try {
1586+
await assertRejects(
1587+
() =>
1588+
transaction.queryArray`SELECT 1`,
1589+
TransactionError,
1590+
);
1591+
} finally {
1592+
connWrite.restore();
1593+
}
1594+
1595+
// Test that connection is OK afterward
1596+
const { rows: result } = await client.queryObject<{ res: number }>({
1597+
text: `SELECT 1`,
1598+
fields: ["res"],
1599+
});
1600+
assertEquals(result[0].res, 1);
1601+
}),
1602+
);
1603+
15011604
Deno.test(
15021605
"Transaction savepoints",
15031606
withClient(async (client) => {

0 commit comments

Comments
 (0)