@@ -95,12 +95,14 @@ class TransportWsEvent {
9595 received = null ,
9696 message = null ,
9797 event = null ;
98+
9899 const TransportWsEvent .opened (WebSocketChannel this .socket)
99100 : type = TransportWsEventType .opened,
100101 payload = null ,
101102 received = null ,
102103 message = null ,
103104 event = null ;
105+
104106 const TransportWsEvent .connected (
105107 WebSocketChannel this .socket,
106108 this .payload,
@@ -116,6 +118,7 @@ class TransportWsEvent {
116118 socket = null ,
117119 message = null ,
118120 event = null ;
121+
119122 const TransportWsEvent .pong (
120123 this .payload, {
121124 required bool this .received,
@@ -130,12 +133,14 @@ class TransportWsEvent {
130133 received = null ,
131134 socket = null ,
132135 event = null ;
136+
133137 const TransportWsEvent .closed (Object this .event)
134138 : type = TransportWsEventType .closed,
135139 payload = null ,
136140 received = null ,
137141 message = null ,
138142 socket = null ;
143+
139144 const TransportWsEvent .error (Object this .event)
140145 : type = TransportWsEventType .error,
141146 payload = null ,
@@ -382,6 +387,17 @@ class TransportWsClientOptions {
382387 /// @default [randomizedExponentialBackoff]
383388 final Future <void > Function (int retries) retryWait;
384389
390+ /// Check if the close event or connection error is fatal. If you return `false` ,
391+ /// the client will fail immediately without additional retries; however, if you
392+ /// return `true` , the client will keep retrying until the `retryAttempts` have
393+ /// been exceeded.
394+ /// The argument is whatever has been thrown during the connection phase.
395+ /// Beware, the library classifies a few close events as fatal regardless of
396+ /// what is returned here. They are listed in the documentation of the
397+ /// `retryAttempts` option.
398+ /// @default [shouldRetryDefault]
399+ final bool Function (Object errOrCloseEvent) shouldRetry;
400+
385401 /// Check if the close event or connection error is fatal. If you return `true` ,
386402 /// the client will fail immediately without additional retries; however, if you
387403 /// return `false` , the client will keep retrying until the `retryAttempts` have
@@ -464,6 +480,7 @@ class TransportWsClientOptions {
464480 this .disablePong = false ,
465481 this .retryAttempts = 0 ,
466482 this .retryWait = randomizedExponentialBackoff,
483+ this .shouldRetry = shouldRetryDefault,
467484 this .isFatalConnectionProblem = isFatalConnectionProblemDefault,
468485 this .eventHandlers,
469486 this .generateID = generateUUID,
@@ -506,6 +523,29 @@ class TransportWsClientOptions {
506523 final v = c.group (0 ) == "x" ? r : (r & 0x3 ) | 0x8 ;
507524 return v.toRadixString (16 );
508525 });
526+
527+ /// By default, connection should not retry on fatal errors
528+ static bool shouldRetryDefault (Object errOrCloseEvent) {
529+ if (errOrCloseEvent is LikeCloseEvent &&
530+ (_isFatalInternalCloseCode (errOrCloseEvent.code) ||
531+ const [
532+ CloseCode .internalServerError,
533+ CloseCode .internalClientError,
534+ CloseCode .badRequest,
535+ CloseCode .badResponse,
536+ CloseCode .unauthorized,
537+ // CloseCode.Forbidden, might grant access out after retry
538+ CloseCode .subprotocolNotAcceptable,
539+ // CloseCode.ConnectionInitialisationTimeout, might not time out after retry
540+ // CloseCode.ConnectionAcknowledgementTimeout, might not time out after retry
541+ CloseCode .subscriberAlreadyExists,
542+ CloseCode .tooManyInitialisationRequests,
543+ // 4499, // Terminated, probably because the socket froze, we want to retry
544+ ].contains (errOrCloseEvent.code))) {
545+ return false ;
546+ }
547+ return true ;
548+ }
509549}
510550
511551class _Connected {
@@ -588,29 +628,15 @@ class _ConnectionState {
588628 /// Checks the `connect` problem and evaluates if the client should retry.
589629 bool shouldRetryConnectOrThrow (Object errOrCloseEvent) {
590630 options.log? .call ("shouldRetryConnectOrThrow $errOrCloseEvent " );
591- // some close codes are worth reporting immediately
592- if (errOrCloseEvent is LikeCloseEvent &&
593- (_isFatalInternalCloseCode (errOrCloseEvent.code) ||
594- const [
595- CloseCode .internalServerError,
596- CloseCode .internalClientError,
597- CloseCode .badRequest,
598- CloseCode .badResponse,
599- CloseCode .unauthorized,
600- // CloseCode.Forbidden, might grant access out after retry
601- CloseCode .subprotocolNotAcceptable,
602- // CloseCode.ConnectionInitialisationTimeout, might not time out after retry
603- // CloseCode.ConnectionAcknowledgementTimeout, might not time out after retry
604- CloseCode .subscriberAlreadyExists,
605- CloseCode .tooManyInitialisationRequests,
606- // 4499, // Terminated, probably because the socket froze, we want to retry
607- ].contains (errOrCloseEvent.code))) {
608- throw errOrCloseEvent;
609- }
610631
611632 // client was disposed, no retries should proceed regardless
612633 if (disposed) return false ;
613634
635+ // some close codes are worth reporting immediately
636+ if (! options.shouldRetry (errOrCloseEvent)) {
637+ throw errOrCloseEvent;
638+ }
639+
614640 // normal closure (possibly all subscriptions have completed)
615641 // if no locks were acquired in the meantime, shouldnt try again
616642 if (errOrCloseEvent is LikeCloseEvent && errOrCloseEvent.code == 1000 ) {
@@ -850,7 +876,7 @@ class _ConnectionState {
850876 ? "DONE"
851877 : LikeCloseEvent (
852878 code: socket.closeCode! ,
853- reason: socket.closeReason! ,
879+ reason: socket.closeReason,
854880 ),
855881 ),
856882 onError: (Object err) => onError? .call (err),
@@ -929,7 +955,9 @@ class _Client extends TransportWsClient {
929955 _Client ({required this .state});
930956
931957 final _ConnectionState state;
958+
932959 _Emitter get emitter => state.emitter;
960+
933961 @override
934962 TransportWsClientOptions get options => state.options;
935963
@@ -1066,6 +1094,7 @@ class _Emitter {
10661094 void Function (TransportWsMessage ) listener,
10671095 ) onMessage;
10681096 final void Function (String logMessage)? log;
1097+
10691098 _Emitter ({
10701099 required this .listeners,
10711100 required this .onMessage,
@@ -1153,7 +1182,7 @@ class LikeCloseEvent {
11531182 final int code;
11541183
11551184 /// Returns the WebSocket connection close reason provided by the server. */
1156- final String reason;
1185+ final String ? reason;
11571186
11581187 final bool ? wasClean;
11591188
0 commit comments