diff --git a/lib/flutter_client_sse.dart b/lib/flutter_client_sse.dart index 57db0b3..fa2894e 100644 --- a/lib/flutter_client_sse.dart +++ b/lib/flutter_client_sse.dart @@ -2,9 +2,12 @@ library flutter_client_sse; import 'dart:async'; import 'dart:convert'; + import 'package:flutter_client_sse/constants/sse_request_type_enum.dart'; import 'package:http/http.dart' as http; + part 'sse_event_model.dart'; +part 'sse_retry_configuration.dart'; /// A client for subscribing to Server-Sent Events (SSE). class SSEClient { @@ -17,22 +20,28 @@ class SSEClient { /// [header] is a map of request headers. /// [body] is an optional request body for POST requests. /// [streamController] is required to persist the stream from the old connection - static void _retryConnection( + static RetryConfiguration _retryConnection( {required SSERequestType method, required String url, required Map header, required StreamController streamController, + required RetryConfiguration config, Map? body}) { print('---RETRY CONNECTION---'); - Future.delayed(Duration(seconds: 5), () { - subscribeToSSE( - method: method, - url: url, - header: header, - body: body, - oldStreamController: streamController, - ); - }); + if (config.infinite || (config.tryCount ?? 0) > 0) { + Future.delayed(Duration(seconds: 5), () { + subscribeToSSE( + method: method, + url: url, + header: header, + body: body, + oldStreamController: streamController, + ); + }); + return config.use(); + } else { + return config; + } } /// Subscribe to Server-Sent Events. @@ -43,18 +52,21 @@ class SSEClient { /// [body] is an optional request body for POST requests. /// /// Returns a [Stream] of [SSEModel] representing the SSE events. - static Stream subscribeToSSE( - {required SSERequestType method, - required String url, - required Map header, - StreamController? oldStreamController, - Map? body}) { + static Stream subscribeToSSE({ + required SSERequestType method, + required String url, + required Map header, + StreamController? oldStreamController, + Map? body, + RetryConfiguration retryConfig = const RetryConfiguration(), + }) { StreamController streamController = StreamController(); if (oldStreamController != null) { streamController = oldStreamController; } var lineRegex = RegExp(r'^([^:]*)(?::)?(?: )?(.*)?$'); var currentSSEModel = SSEModel(data: '', id: '', event: ''); + print("--SUBSCRIBING TO SSE---"); while (true) { try { @@ -121,47 +133,53 @@ class SSEClient { default: print('---ERROR---'); print(dataLine); - _retryConnection( + retryConfig = _retryConnection( method: method, url: url, header: header, streamController: streamController, + config: retryConfig, ); } }, onError: (e, s) { print('---ERROR---'); print(e); - _retryConnection( + + retryConfig = _retryConnection( method: method, url: url, header: header, - body: body, streamController: streamController, + config: retryConfig, ); }, ); }, onError: (e, s) { print('---ERROR---'); print(e); - _retryConnection( + retryConfig = _retryConnection( method: method, url: url, header: header, - body: body, streamController: streamController, + config: retryConfig, ); }); } catch (e) { print('---ERROR---'); print(e); - _retryConnection( + retryConfig = _retryConnection( method: method, url: url, header: header, - body: body, streamController: streamController, + config: retryConfig, ); + } finally { + if (retryConfig.tryCount == 0) { + return Stream.error('rety exceeded'); + } } return streamController.stream; } diff --git a/lib/sse_retry_configuration.dart b/lib/sse_retry_configuration.dart new file mode 100644 index 0000000..4eec771 --- /dev/null +++ b/lib/sse_retry_configuration.dart @@ -0,0 +1,31 @@ +part of 'flutter_client_sse.dart'; + +class RetryConfiguration { + final int? tryCount; + final bool infinite; + + const RetryConfiguration({this.tryCount, this.infinite = true}) + : assert(!(tryCount == null && !infinite), + 'tryCount must be null if infinite is true'); + + RetryConfiguration copyWith({ + int? tryCount, + bool? infinite, + }) { + return RetryConfiguration( + tryCount: tryCount ?? this.tryCount, + infinite: infinite ?? this.infinite, + ); + } + + RetryConfiguration use() { + if (infinite) { + return this; + } else { + assert(tryCount != null, + "this should not be null because infinite is false"); + + return copyWith(tryCount: tryCount! - 1); + } + } +} diff --git a/pubspec.lock b/pubspec.lock index 8d66057..594504e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -87,26 +87,26 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" matcher: dependency: transitive description: @@ -119,18 +119,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.15.0" path: dependency: transitive description: @@ -188,10 +188,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" typed_data: dependency: transitive description: @@ -212,10 +212,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.5" sdks: - dart: ">=3.2.0-0 <4.0.0" - flutter: ">=1.17.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/pubspec.yaml b/pubspec.yaml index c7fd9bf..7917270 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: flutter_client_sse description: Dart package to help consume SSE API. It consumes server sent events by returning parsed model of the event, id, and the data -version: 2.0.3 +version: 2.0.4 homepage: https://github.com/pratikbaid3/flutter_client_sse environment: - sdk: '>=2.12.0 <4.0.0' + sdk: ">=2.12.0 <4.0.0" flutter: ">=1.17.0" dependencies: @@ -17,4 +17,3 @@ dev_dependencies: sdk: flutter flutter: -