Skip to content

Commit e623f6d

Browse files
committed
feat(firehose): add exception hierarchy and depend on shared record cache
- AmplifyFirehoseException sealed hierarchy with .from() mapper - FirehoseStorageException, FirehoseValidationException, FirehoseLimitExceededException, FirehoseUnknownException, FirehoseClientClosedException - Depend on amplify_record_cache_dart for storage/caching infrastructure - Re-export shared FlushStrategy, FlushData, RecordData, ClearCacheData - Export Firehose SDK escape hatch types - Exception mapping tests - Slim pubspec: removed direct drift/web/db deps (now transitive via shared pkg)
1 parent c6453f1 commit e623f6d

4 files changed

Lines changed: 206 additions & 11 deletions

File tree

packages/kinesis/amplify_firehose_dart/lib/amplify_firehose_dart.dart

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,22 @@
44
/// Amplify Amazon Data Firehose client for Dart.
55
library;
66

7+
// Re-export shared types used in the public API
8+
export 'package:amplify_record_cache_dart/amplify_record_cache_dart.dart'
9+
show
10+
FlushStrategy,
11+
FlushInterval,
12+
FlushNone,
13+
FlushData,
14+
RecordData,
15+
ClearCacheData;
16+
17+
// Exceptions
18+
export 'src/exception/amplify_firehose_exception.dart';
719
// SDK client (for escape hatch)
8-
// Exports will be added as implementation PRs land.
20+
export 'src/sdk/firehose.dart'
21+
show
22+
FirehoseClient,
23+
PutRecordBatchInput,
24+
PutRecordBatchOutput,
25+
PutRecordBatchResponseEntry;
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import 'package:amplify_core/amplify_core.dart';
5+
import 'package:amplify_record_cache_dart/amplify_record_cache_dart.dart';
6+
7+
/// Default recovery suggestion for errors.
8+
const String defaultRecoverySuggestion =
9+
'Inspect the underlying error for more details.';
10+
11+
/// {@template amplify_firehose.amplify_firehose_exception}
12+
/// Base exception for Amplify Firehose errors.
13+
/// {@endtemplate}
14+
sealed class AmplifyFirehoseException extends AmplifyException {
15+
/// {@macro amplify_firehose.amplify_firehose_exception}
16+
const AmplifyFirehoseException(
17+
super.message, {
18+
super.recoverySuggestion,
19+
super.underlyingException,
20+
});
21+
22+
/// Maps an arbitrary error into the appropriate
23+
/// [AmplifyFirehoseException] subtype.
24+
static AmplifyFirehoseException from(Object error) => switch (error) {
25+
final AmplifyFirehoseException e => e,
26+
final RecordCacheValidationException e => FirehoseValidationException(
27+
e.message,
28+
recoverySuggestion: e.recoverySuggestion,
29+
),
30+
final RecordCacheLimitExceededException e => FirehoseLimitExceededException(
31+
message: e.message,
32+
recoverySuggestion: e.recoverySuggestion,
33+
),
34+
final RecordCacheDatabaseException e => FirehoseStorageException(
35+
e.message,
36+
recoverySuggestion: e.recoverySuggestion,
37+
underlyingException: e.cause,
38+
),
39+
final Exception e => FirehoseUnknownException(
40+
e.toString(),
41+
underlyingException: e,
42+
),
43+
_ => FirehoseUnknownException(error.toString()),
44+
};
45+
}
46+
47+
/// {@template amplify_firehose.firehose_storage_exception}
48+
/// Thrown when a local cache/database error occurs.
49+
/// {@endtemplate}
50+
final class FirehoseStorageException extends AmplifyFirehoseException {
51+
/// {@macro amplify_firehose.firehose_storage_exception}
52+
const FirehoseStorageException(
53+
super.message, {
54+
super.recoverySuggestion,
55+
super.underlyingException,
56+
});
57+
58+
@override
59+
String get runtimeTypeName => 'FirehoseStorageException';
60+
}
61+
62+
/// {@template amplify_firehose.firehose_limit_exceeded_exception}
63+
/// Thrown when the local cache is full.
64+
/// {@endtemplate}
65+
final class FirehoseLimitExceededException extends AmplifyFirehoseException {
66+
/// {@macro amplify_firehose.firehose_limit_exceeded_exception}
67+
const FirehoseLimitExceededException({
68+
String? message,
69+
String? recoverySuggestion,
70+
}) : super(
71+
message ?? 'Cache is full',
72+
recoverySuggestion:
73+
recoverySuggestion ?? 'Call flush() or clearCache().',
74+
);
75+
76+
@override
77+
String get runtimeTypeName => 'FirehoseLimitExceededException';
78+
}
79+
80+
/// {@template amplify_firehose.firehose_validation_exception}
81+
/// Thrown when record input validation fails (e.g. oversized record).
82+
/// {@endtemplate}
83+
final class FirehoseValidationException extends AmplifyFirehoseException {
84+
/// {@macro amplify_firehose.firehose_validation_exception}
85+
const FirehoseValidationException(super.message, {super.recoverySuggestion});
86+
87+
@override
88+
String get runtimeTypeName => 'FirehoseValidationException';
89+
}
90+
91+
/// {@template amplify_firehose.firehose_unknown_exception}
92+
/// Catch-all for unexpected errors.
93+
/// {@endtemplate}
94+
final class FirehoseUnknownException extends AmplifyFirehoseException {
95+
/// {@macro amplify_firehose.firehose_unknown_exception}
96+
const FirehoseUnknownException(super.message, {super.underlyingException});
97+
98+
@override
99+
String get runtimeTypeName => 'FirehoseUnknownException';
100+
}
101+
102+
/// {@template amplify_firehose.client_closed_exception}
103+
/// Thrown when an operation is attempted on a closed client.
104+
/// {@endtemplate}
105+
final class FirehoseClientClosedException extends AmplifyFirehoseException {
106+
/// {@macro amplify_firehose.client_closed_exception}
107+
const FirehoseClientClosedException()
108+
: super(
109+
'Client has been closed',
110+
recoverySuggestion: 'Create a new AmplifyFirehoseClient instance.',
111+
);
112+
113+
@override
114+
String get runtimeTypeName => 'FirehoseClientClosedException';
115+
}

packages/kinesis/amplify_firehose_dart/pubspec.yaml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,20 @@ environment:
1717

1818
dependencies:
1919
amplify_core: ">=2.10.0 <2.11.0"
20-
amplify_db_common_dart: ">=0.4.14 <0.5.0"
21-
amplify_foundation_dart: ">=2.10.0 <2.11.0"
22-
amplify_foundation_dart_bridge: ">=2.10.0 <2.11.0"
20+
amplify_foundation_dart: ">=2.11.0 <2.12.0"
21+
amplify_foundation_dart_bridge: ">=2.11.0 <2.12.0"
22+
amplify_record_cache_dart: ">=0.1.0 <0.2.0"
2323
aws_common: ">=0.7.12 <0.8.0"
2424
aws_signature_v4: ">=0.6.10 <0.7.0"
2525
built_collection: ^5.1.1
2626
built_value: ^8.10.1
27-
drift: ^2.25.0
2827
meta: ^1.16.0
2928
smithy: ">=0.7.10 <0.8.0"
3029
smithy_aws: ">=0.7.10 <0.8.0"
31-
synchronized: ^3.3.0
32-
web: ^1.1.1
3330

3431
dev_dependencies:
3532
amplify_lints: ">=3.1.4 <3.2.0"
36-
build_runner: ^2.4.15
37-
build_version: ^2.1.1
38-
built_value_generator: ^8.10.1
39-
drift_dev: ^2.25.1
33+
drift: ^2.25.0
4034
fake_async: ^1.3.0
4135
mocktail: ^1.0.0
4236
test: ^1.22.1
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import 'package:amplify_firehose_dart/src/exception/amplify_firehose_exception.dart';
5+
import 'package:amplify_record_cache_dart/amplify_record_cache_dart.dart';
6+
import 'package:test/test.dart';
7+
8+
void main() {
9+
group('AmplifyFirehoseException.from', () {
10+
test('passes through AmplifyFirehoseException unchanged', () {
11+
const original = FirehoseStorageException('msg');
12+
final result = AmplifyFirehoseException.from(original);
13+
expect(identical(result, original), isTrue);
14+
});
15+
16+
test('converts RecordCacheValidationException '
17+
'to FirehoseValidationException', () {
18+
const cause = RecordCacheValidationException('bad input', 'fix it');
19+
final result = AmplifyFirehoseException.from(cause);
20+
expect(result, isA<FirehoseValidationException>());
21+
expect(result.message, 'bad input');
22+
expect(result.recoverySuggestion, 'fix it');
23+
});
24+
25+
test(
26+
'converts RecordCacheDatabaseException to FirehoseStorageException',
27+
() {
28+
final underlying = Exception('sqlite error');
29+
final cause = RecordCacheDatabaseException(
30+
'db error',
31+
'retry',
32+
underlying,
33+
);
34+
final result = AmplifyFirehoseException.from(cause);
35+
expect(result, isA<FirehoseStorageException>());
36+
expect(result.message, 'db error');
37+
expect(result.recoverySuggestion, 'retry');
38+
expect(result.underlyingException, underlying);
39+
},
40+
);
41+
42+
test('converts RecordCacheLimitExceededException '
43+
'to FirehoseLimitExceededException', () {
44+
const cause = RecordCacheLimitExceededException(
45+
'cache full',
46+
'flush first',
47+
);
48+
final result = AmplifyFirehoseException.from(cause);
49+
expect(result, isA<FirehoseLimitExceededException>());
50+
expect(result.message, 'cache full');
51+
expect(result.recoverySuggestion, 'flush first');
52+
});
53+
54+
test('converts unknown Exception to FirehoseUnknownException', () {
55+
final cause = Exception('something unexpected');
56+
final result = AmplifyFirehoseException.from(cause);
57+
expect(result, isA<FirehoseUnknownException>());
58+
expect(result.underlyingException, cause);
59+
});
60+
61+
test('converts non-Exception error to FirehoseUnknownException', () {
62+
const error = 'a string error';
63+
final result = AmplifyFirehoseException.from(error);
64+
expect(result, isA<FirehoseUnknownException>());
65+
expect(result.message, 'a string error');
66+
expect(result.underlyingException, isNull);
67+
});
68+
});
69+
}

0 commit comments

Comments
 (0)