Skip to content

Commit 91e3523

Browse files
committed
tests: Add tests for client auto-reconnect after connection drop behaviour
1 parent 58dd75c commit 91e3523

1 file changed

Lines changed: 99 additions & 2 deletions

File tree

tests/query_client_test.ts

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
assertRejects,
1414
assertThrows,
1515
} from "jsr:@std/assert@1.0.10";
16+
import { MockError, stub } from "jsr:@std/testing/mock";
1617
import { getMainConfiguration } from "./config.ts";
1718
import type { PoolClient, QueryClient } from "../client.ts";
1819
import type { ClientOptions } from "../connection/connection_params.ts";
@@ -694,9 +695,13 @@ Deno.test(
694695
);
695696

696697
// This test depends on the assumption that all clients will default to
697-
// one reconneciton by default
698+
// one reconnection by default
699+
//
700+
// It also specifically tests the case where the database system sends a
701+
// graceful disconnect, not the case where the database connection is just
702+
// closed due to the database process crashing or being killed.
698703
Deno.test(
699-
"Default reconnection",
704+
"Default reconnection after graceful database connection close",
700705
withClient(async (client) => {
701706
await assertRejects(
702707
() =>
@@ -714,6 +719,64 @@ Deno.test(
714719
}),
715720
);
716721

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

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

0 commit comments

Comments
 (0)