Skip to content

Commit

Permalink
Do not rely on message text when transforming exception.
Browse files Browse the repository at this point in the history
  • Loading branch information
isoos committed Sep 15, 2024
1 parent c212668 commit d440f04
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 24 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
- `EncoderFn` value converter for generic Dart object -> Postgres-encoded bytes
(for values where type is not specified).
- `DatabaseInfo` tracks information about relations and oids (currently limited to `RelationMessage` caching).
- **Behaviour / soft-breaking changes**:
- **Behaviour changes**, may be breaking in some cases:
- Preparing/executing a stamement on the main connection while in a `runTx` callback will throw an exception.
- Setting `timeout` will try to actively cancel the current statement using a new connection.
- `ServerException` may be transformed into `_PgQueryCancelledException` which is both `PgException` and `TimeoutException` (but no longer `ServerException`).
- **API deprecations**:
- Deprecated `TupleDataColumn.data`, use `.value` instead (for binary protocol messages).
- Deprecated some logical replication message parsing method.
- Removed `@internal`-annotated methods from the public API of `ServerException` and `Severity`.
- `ServerException` may be transformed into `_PgTimeoutException` which is both `PgException` and `TimeoutException` (but no longer `ServerException`).

## 3.3.0

Expand Down
24 changes: 10 additions & 14 deletions lib/src/exceptions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -190,27 +190,23 @@ ServerException buildExceptionFromErrorFields(List<ErrorField> errorFields) {
);
}

PgException transformServerException(
ServerException ex, {
bool timeoutTriggered = false,
}) {
if (ex.code == '57014' &&
ex.message == 'canceling statement due to statement timeout') {
return _PgTimeoutException(
['${ex.code}:', ex.message, ex.trace].whereType<String>().join(' '),
);
}
if (ex.code == '57014' && timeoutTriggered) {
return _PgTimeoutException(
PgException transformServerException(ServerException ex) {
if (ex.code == '57014') {
return _PgQueryCancelledException(
['${ex.code}:', ex.message, ex.trace].whereType<String>().join(' '),
severity: ex.severity,
);
}
return ex;
}

class _PgTimeoutException extends PgException implements TimeoutException {
class _PgQueryCancelledException extends PgException
implements TimeoutException {
@override
late final duration = null;

_PgTimeoutException(super.message) : super(severity: Severity.error);
_PgQueryCancelledException(
super.message, {
required super.severity,
});
}
7 changes: 0 additions & 7 deletions lib/src/v3/connection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -892,11 +892,9 @@ class _PgResultStreamSubscription
required List<ResultRow> items,
required Duration? timeout,
}) async {
bool timeoutTriggered = false;
final cancelTimer = timeout == null
? null
: Timer(timeout, () async {
timeoutTriggered = true;
await connection.cancelPendingStatement();
});
try {
Expand All @@ -906,11 +904,6 @@ class _PgResultStreamSubscription
affectedRows: await affectedRows,
schema: await schema,
);
} on ServerException catch (e) {
if (timeoutTriggered) {
throw transformServerException(e, timeoutTriggered: timeoutTriggered);
}
rethrow;
} finally {
cancelTimer?.cancel();
}
Expand Down
10 changes: 9 additions & 1 deletion test/timeout_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,15 @@ void main() {
test('Cancel current statement through a new connection', () async {
final f = conn.execute('SELECT pg_sleep(2);');
await (conn as PgConnectionImplementation).cancelPendingStatement();
await expectLater(f, throwsA(isA<ServerException>()));
await expectLater(
f,
throwsA(
allOf(
isA<PgException>(),
isA<TimeoutException>(),
),
),
);
// connection is still usable
final rs = await conn.execute('SELECT 1;');
expect(rs[0][0], 1);
Expand Down

0 comments on commit d440f04

Please sign in to comment.