Skip to content

Commit 5a24e72

Browse files
authored
Implementing Pool.close(force: true). (#405)
1 parent 527f53c commit 5a24e72

File tree

3 files changed

+30
-25
lines changed

3 files changed

+30
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Fix: do not close connection after an empty statement.
66
- Fix: `close(force: true)` does not cause uncaught exception.
7+
- Implemented `Pool.close(force: true)` (using [davidmartos96](https://github.com/davidmartos96)'s [#397](https://github.com/isoos/postgresql-dart/pull/397) as baseline).
78

89
## 3.4.5
910

lib/src/pool/pool_impl.dart

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,31 @@ class PoolImplementation<L> implements Pool<L> {
3030
1,
3131
timeout: _settings.connectTimeout,
3232
);
33+
bool _closing = false;
3334

3435
PoolImplementation(this._selector, PoolSettings? settings)
3536
: _settings = ResolvedPoolSettings(settings);
3637

3738
@override
38-
bool get isOpen => !_semaphore.isClosed;
39+
bool get isOpen => !_closing;
3940

4041
@override
4142
Future<void> get closed => _semaphore.done;
4243

4344
@override
4445
Future<void> close({bool force = false}) async {
45-
// TODO: Implement force close.
46-
await _semaphore.close();
46+
_closing = true;
47+
final semaphoreFuture = _semaphore.close();
4748

4849
// Connections are closed when they are returned to the pool if it's closed.
4950
// We still need to close statements that are currently unused.
5051
for (final connection in [..._connections]) {
51-
if (!connection._isInUse) {
52-
await connection._dispose();
52+
if (force || !connection._isInUse) {
53+
await connection._dispose(force: force);
5354
}
5455
}
56+
57+
await semaphoreFuture;
5558
}
5659

5760
@override
@@ -164,7 +167,7 @@ class PoolImplementation<L> implements Pool<L> {
164167
// well.
165168
if (connection != null) {
166169
connection._elapsedInUse += sw.elapsed;
167-
if (_semaphore.isClosed || !reuse || !connection.isOpen) {
170+
if (_closing || !reuse || !connection.isOpen) {
168171
await connection._dispose();
169172
} else {
170173
// Allow the connection to be re-used later.
@@ -255,9 +258,9 @@ class _PoolConnection implements Connection {
255258
return false;
256259
}
257260

258-
Future<void> _dispose() async {
261+
Future<void> _dispose({bool force = false}) async {
259262
_pool._connections.remove(this);
260-
await _connection.close();
263+
await _connection.close(force: force);
261264
}
262265

263266
@override

test/pool_test.dart

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ void main() {
211211
});
212212
});
213213

214-
group(skip: 'not implemented', 'force close', () {
214+
group('force close', () {
215215
Future<Pool> openPool(PostgresServer server) async {
216216
final pool = Pool.withEndpoints(
217217
[await server.endpoint()],
@@ -235,35 +235,36 @@ void main() {
235235
}
236236

237237
withPostgresServer('pool session', (server) {
238-
test('', () async {
238+
test('pool session', () async {
239239
final pool = await openPool(server);
240-
// ignore: unawaited_futures
241-
runLongQuery(pool);
240+
final started = Completer();
241+
final rs = pool.run((s) async {
242+
started.complete();
243+
await runLongQuery(s);
244+
});
242245
// let it start
246+
await started.future;
243247
await Future.delayed(const Duration(milliseconds: 100));
244248
await expectPoolClosesForcefully(pool);
249+
250+
await expectLater(() => rs, throwsA(isA<PgException>()));
245251
});
246252
});
247253

248254
withPostgresServer('tx session', (server) {
249-
test('', () async {
255+
test('tx', () async {
250256
final pool = await openPool(server);
251-
// Ignore async error, it will fail when the connection is closed and it tries to do COMMIT
252-
pool.runTx(runLongQuery).ignore();
257+
final started = Completer();
258+
final rs = pool.runTx((s) async {
259+
started.complete();
260+
await runLongQuery(s);
261+
});
253262
// let it start
263+
await started.future;
254264
await Future.delayed(const Duration(milliseconds: 100));
255265
await expectPoolClosesForcefully(pool);
256-
});
257-
});
258266

259-
withPostgresServer('run session', (server) {
260-
test('', () async {
261-
final pool = await openPool(server);
262-
// ignore: unawaited_futures
263-
pool.run(runLongQuery);
264-
// let it start
265-
await Future.delayed(const Duration(milliseconds: 100));
266-
await expectPoolClosesForcefully(pool);
267+
await expectLater(() => rs, throwsA(isA<PgException>()));
267268
});
268269
});
269270
});

0 commit comments

Comments
 (0)